Skip to content

Commit 64bb019

Browse files
authored
HDDS-14238. Move RDBBatchOperation Byte comparison to native comparison for optimization (#9550)
1 parent 563b9d5 commit 64bb019

File tree

3 files changed

+51
-35
lines changed

3 files changed

+51
-35
lines changed

hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/db/RDBBatchOperation.java

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
package org.apache.hadoop.hdds.utils.db;
1919

20-
import static org.apache.hadoop.hdds.StringUtils.bytes2String;
20+
import static org.apache.ratis.util.Preconditions.assertTrue;
2121

2222
import com.google.common.base.Preconditions;
2323
import java.io.Closeable;
@@ -30,10 +30,13 @@
3030
import java.util.function.Supplier;
3131
import org.apache.hadoop.hdds.utils.IOUtils;
3232
import org.apache.hadoop.hdds.utils.db.RocksDatabase.ColumnFamily;
33+
import org.apache.hadoop.hdds.utils.db.managed.ManagedDirectSlice;
34+
import org.apache.hadoop.hdds.utils.db.managed.ManagedSlice;
3335
import org.apache.hadoop.hdds.utils.db.managed.ManagedWriteBatch;
3436
import org.apache.hadoop.hdds.utils.db.managed.ManagedWriteOptions;
3537
import org.apache.ratis.util.TraditionalBinaryPrefix;
3638
import org.apache.ratis.util.UncheckedAutoCloseable;
39+
import org.rocksdb.AbstractSlice;
3740
import org.slf4j.Logger;
3841
import org.slf4j.LoggerFactory;
3942

@@ -80,26 +83,26 @@ private static String countSize2String(int count, long size) {
8083
* To implement {@link #equals(Object)} and {@link #hashCode()}
8184
* based on the contents of the bytes.
8285
*/
83-
static final class Bytes {
84-
private final byte[] array;
85-
private final CodecBuffer buffer;
86+
static final class Bytes implements Closeable {
87+
private final AbstractSlice<?> slice;
8688
/** Cache the hash value. */
8789
private final int hash;
8890

89-
Bytes(CodecBuffer buffer) {
90-
this.array = null;
91-
this.buffer = Objects.requireNonNull(buffer, "buffer == null");
92-
this.hash = buffer.asReadOnlyByteBuffer().hashCode();
91+
static Bytes newBytes(CodecBuffer buffer) {
92+
return buffer.isDirect() ? new Bytes(buffer.asReadOnlyByteBuffer()) : new Bytes(buffer.getArray());
9393
}
9494

95-
Bytes(byte[] array) {
96-
this.array = array;
97-
this.buffer = null;
98-
this.hash = ByteBuffer.wrap(array).hashCode();
95+
Bytes(ByteBuffer buffer) {
96+
Objects.requireNonNull(buffer, "buffer == null");
97+
assertTrue(buffer.isDirect(), "buffer must be direct");
98+
this.slice = new ManagedDirectSlice(buffer);
99+
this.hash = buffer.hashCode();
99100
}
100101

101-
ByteBuffer asReadOnlyByteBuffer() {
102-
return buffer.asReadOnlyByteBuffer();
102+
Bytes(byte[] array) {
103+
Objects.requireNonNull(array, "array == null");
104+
this.slice = new ManagedSlice(array);
105+
this.hash = ByteBuffer.wrap(array).hashCode();
103106
}
104107

105108
@Override
@@ -113,11 +116,7 @@ public boolean equals(Object obj) {
113116
if (this.hash != that.hash) {
114117
return false;
115118
}
116-
final ByteBuffer thisBuf = this.array != null ?
117-
ByteBuffer.wrap(this.array) : this.asReadOnlyByteBuffer();
118-
final ByteBuffer thatBuf = that.array != null ?
119-
ByteBuffer.wrap(that.array) : that.asReadOnlyByteBuffer();
120-
return thisBuf.equals(thatBuf);
119+
return slice.equals(that.slice);
121120
}
122121

123122
@Override
@@ -127,12 +126,21 @@ public int hashCode() {
127126

128127
@Override
129128
public String toString() {
130-
return array != null ? bytes2String(array)
131-
: bytes2String(asReadOnlyByteBuffer());
129+
return slice.toString();
130+
}
131+
132+
@Override
133+
public void close() {
134+
slice.close();
132135
}
133136
}
134137

135138
private abstract static class Op implements Closeable {
139+
private final Bytes keyBytes;
140+
141+
private Op(Bytes keyBytes) {
142+
this.keyBytes = keyBytes;
143+
}
136144

137145
abstract void apply(ColumnFamily family, ManagedWriteBatch batch) throws RocksDatabaseException;
138146

@@ -148,6 +156,9 @@ int totalLength() {
148156

149157
@Override
150158
public void close() {
159+
if (keyBytes != null) {
160+
keyBytes.close();
161+
}
151162
}
152163
}
153164

@@ -157,7 +168,8 @@ public void close() {
157168
private static final class DeleteOp extends Op {
158169
private final byte[] key;
159170

160-
private DeleteOp(byte[] key) {
171+
private DeleteOp(byte[] key, Bytes keyBytes) {
172+
super(Objects.requireNonNull(keyBytes, "keyBytes == null"));
161173
this.key = Objects.requireNonNull(key, "key == null");
162174
}
163175

@@ -180,7 +192,8 @@ private final class PutOp extends Op {
180192
private final CodecBuffer value;
181193
private final AtomicBoolean closed = new AtomicBoolean(false);
182194

183-
private PutOp(CodecBuffer key, CodecBuffer value) {
195+
private PutOp(CodecBuffer key, CodecBuffer value, Bytes keyBytes) {
196+
super(keyBytes);
184197
this.key = key;
185198
this.value = value;
186199
}
@@ -217,7 +230,8 @@ private static final class ByteArrayPutOp extends Op {
217230
private final byte[] key;
218231
private final byte[] value;
219232

220-
private ByteArrayPutOp(byte[] key, byte[] value) {
233+
private ByteArrayPutOp(byte[] key, byte[] value, Bytes keyBytes) {
234+
super(keyBytes);
221235
this.key = Objects.requireNonNull(key, "key == null");
222236
this.value = Objects.requireNonNull(value, "value == null");
223237
}
@@ -323,20 +337,20 @@ void overwriteIfExists(Bytes key, Op op) {
323337
void put(CodecBuffer key, CodecBuffer value) {
324338
putCount++;
325339
// always release the key with the value
326-
Bytes keyBytes = new Bytes(key);
327-
overwriteIfExists(keyBytes, new PutOp(key, value));
340+
Bytes keyBytes = Bytes.newBytes(key);
341+
overwriteIfExists(keyBytes, new PutOp(key, value, keyBytes));
328342
}
329343

330344
void put(byte[] key, byte[] value) {
331345
putCount++;
332346
Bytes keyBytes = new Bytes(key);
333-
overwriteIfExists(keyBytes, new ByteArrayPutOp(key, value));
347+
overwriteIfExists(keyBytes, new ByteArrayPutOp(key, value, keyBytes));
334348
}
335349

336350
void delete(byte[] key) {
337351
delCount++;
338352
Bytes keyBytes = new Bytes(key);
339-
overwriteIfExists(keyBytes, new DeleteOp(key));
353+
overwriteIfExists(keyBytes, new DeleteOp(key, keyBytes));
340354
}
341355

342356
String putString(int keySize, int valueSize) {

hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/utils/db/TestCodec.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import static java.nio.charset.StandardCharsets.UTF_8;
2121
import static org.apache.hadoop.hdds.utils.db.CodecTestUtil.gc;
22+
import static org.apache.hadoop.hdds.utils.db.RDBBatchOperation.Bytes.newBytes;
2223
import static org.assertj.core.api.Assertions.assertThat;
2324
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
2425
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -35,6 +36,7 @@
3536
import java.util.concurrent.ThreadLocalRandom;
3637
import java.util.function.Consumer;
3738
import org.apache.hadoop.hdds.utils.db.RDBBatchOperation.Bytes;
39+
import org.apache.hadoop.hdds.utils.db.managed.ManagedRocksObjectUtils;
3840
import org.junit.jupiter.api.Test;
3941
import org.junit.jupiter.api.function.Executable;
4042
import org.slf4j.Logger;
@@ -49,6 +51,7 @@ public final class TestCodec {
4951

5052
static {
5153
CodecBuffer.enableLeakDetection();
54+
ManagedRocksObjectUtils.loadRocksDBLibrary();
5255
}
5356

5457
@Test
@@ -289,17 +292,15 @@ public void testUuidCodec() throws Exception {
289292
public static <T> void runTest(Codec<T> codec, T original,
290293
Integer serializedSize) throws Exception {
291294
CodecTestUtil.runTest(codec, original, serializedSize, null);
292-
runTestBytes(original, codec);
295+
runTestBytes(original, codec, CodecBuffer.Allocator.HEAP);
296+
runTestBytes(original, codec, CodecBuffer.Allocator.DIRECT);
293297
}
294298

295-
static <T> void runTestBytes(T object, Codec<T> codec) throws IOException {
299+
static <T> void runTestBytes(T object, Codec<T> codec, CodecBuffer.Allocator allocator) throws IOException {
296300
final byte[] array = codec.toPersistedFormat(object);
297301
final Bytes fromArray = new Bytes(array);
298-
299-
try (CodecBuffer buffer = codec.toCodecBuffer(object,
300-
CodecBuffer.Allocator.HEAP)) {
301-
final Bytes fromBuffer = new Bytes(buffer);
302-
302+
try (CodecBuffer buffer = codec.toCodecBuffer(object, allocator)) {
303+
final Bytes fromBuffer = newBytes(buffer);
303304
assertEquals(fromArray.hashCode(), fromBuffer.hashCode());
304305
assertEquals(fromArray, fromBuffer);
305306
assertEquals(fromBuffer, fromArray);

pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1959,6 +1959,7 @@
19591959
<allowedImport>org.rocksdb.ColumnFamilyHandle</allowedImport>
19601960
<allowedImport>org.rocksdb.Env</allowedImport>
19611961
<allowedImport>org.rocksdb.Statistics</allowedImport>
1962+
<allowedImport>org.rocksdb.AbstractSlice</allowedImport>
19621963
<!-- Allow RocksDB constants and static methods to be used. -->
19631964
<allowedImport>org.rocksdb.RocksDB.*</allowedImport>
19641965
</allowedImports>

0 commit comments

Comments
 (0)