-
Notifications
You must be signed in to change notification settings - Fork 6.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RocksJava: Improve 'get' performance #7597
Open
alucarded
wants to merge
15
commits into
facebook:main
Choose a base branch
from
alucarded:bench
base: main
Could not load branches
Branch not found: {{ refName }}
Could not load tags
Nothing to show
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
ef06948
Add more RocksDB.get() benchmarks
alucarded 0b31883
Add to java/jmh/README.md info on how to run with local RocksJava
alucarded 3412d99
Update version pom
alucarded 4932b9a
Add RocksDB.get() with ByteBuffer test
alucarded 71d6b0b
Parametrize JMH SingleGetBenchmarks
alucarded 2ce6db6
Add value only ByteBuffer RocksDB.get() version
alucarded fde1e85
Unsafe investigation
alucarded 4d2799f
Use GetPrimitiveArrayCritical instead of GetByteArrayRegion
alucarded 88ae2c3
Add FastBuffer
alucarded 5d134dd
Update Unsafe benchmark with FastBuffer and PinnableSlice
alucarded 567bf24
Update version
alucarded 77c4fa1
Revert "Add value only ByteBuffer RocksDB.get() version"
alucarded f5d247f
Ran `make format`
alucarded cf2891b
Fix GetPrimitiveArrayCritical
alucarded 8175988
Add missing files to CMakeLists.txt
alucarded File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,24 @@ | ||
/** | ||
* Copyright (c) 2011-present, Facebook, Inc. All rights reserved. | ||
* This source code is licensed under both the GPLv2 (found in the | ||
* COPYING file in the root directory) and Apache 2.0 License | ||
* (found in the LICENSE.Apache file in the root directory). | ||
* This source code is licensed under both the GPLv2 (found in the | ||
* COPYING file in the root directory) and Apache 2.0 License | ||
* (found in the LICENSE.Apache file in the root directory). | ||
*/ | ||
package org.rocksdb.jmh; | ||
|
||
import org.openjdk.jmh.annotations.*; | ||
import org.rocksdb.*; | ||
import org.rocksdb.util.FileUtils; | ||
import static org.rocksdb.util.KVUtils.ba; | ||
|
||
import java.io.IOException; | ||
import java.nio.ByteBuffer; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.List; | ||
import java.util.concurrent.atomic.AtomicInteger; | ||
|
||
import static org.rocksdb.util.KVUtils.ba; | ||
import org.openjdk.jmh.annotations.*; | ||
import org.rocksdb.*; | ||
import org.rocksdb.util.FileUtils; | ||
|
||
@State(Scope.Benchmark) | ||
public class GetBenchmarks { | ||
|
@@ -33,13 +34,22 @@ public class GetBenchmarks { | |
@Param("100000") | ||
int keyCount; | ||
|
||
@Param({"12", "64", "128"}) int keySize; | ||
|
||
@Param({"64", "1024", "65536"}) int valueSize; | ||
|
||
Path dbDir; | ||
DBOptions options; | ||
ReadOptions readOptions; | ||
int cfs = 0; // number of column families | ||
private AtomicInteger cfHandlesIdx; | ||
ColumnFamilyHandle[] cfHandles; | ||
RocksDB db; | ||
private final AtomicInteger keyIndex = new AtomicInteger(); | ||
private ByteBuffer keyBuf; | ||
private ByteBuffer valueBuf; | ||
private byte[] keyArr; | ||
private byte[] valueArr; | ||
|
||
@Setup(Level.Trial) | ||
public void setup() throws IOException, RocksDBException { | ||
|
@@ -50,6 +60,7 @@ public void setup() throws IOException, RocksDBException { | |
options = new DBOptions() | ||
.setCreateIfMissing(true) | ||
.setCreateMissingColumnFamilies(true); | ||
readOptions = new ReadOptions(); | ||
|
||
final List<ColumnFamilyDescriptor> cfDescriptors = new ArrayList<>(); | ||
cfDescriptors.add(new ColumnFamilyDescriptor(RocksDB.DEFAULT_COLUMN_FAMILY)); | ||
|
@@ -74,16 +85,32 @@ public void setup() throws IOException, RocksDBException { | |
cfHandles = cfHandlesList.toArray(new ColumnFamilyHandle[0]); | ||
|
||
// store initial data for retrieving via get | ||
for (int i = 0; i < cfs; i++) { | ||
keyArr = new byte[keySize]; | ||
valueArr = new byte[valueSize]; | ||
Arrays.fill(keyArr, (byte) 0x30); | ||
Arrays.fill(valueArr, (byte) 0x30); | ||
for (int i = 0; i <= cfs; i++) { | ||
for (int j = 0; j < keyCount; j++) { | ||
db.put(cfHandles[i], ba("key" + j), ba("value" + j)); | ||
final byte[] keyPrefix = ba("key" + j); | ||
final byte[] valuePrefix = ba("value" + j); | ||
System.arraycopy(keyPrefix, 0, keyArr, 0, keyPrefix.length); | ||
System.arraycopy(valuePrefix, 0, valueArr, 0, valuePrefix.length); | ||
db.put(cfHandles[i], keyArr, valueArr); | ||
} | ||
} | ||
|
||
try (final FlushOptions flushOptions = new FlushOptions() | ||
.setWaitForFlush(true)) { | ||
try (final FlushOptions flushOptions = new FlushOptions().setWaitForFlush(true)) { | ||
db.flush(flushOptions); | ||
} | ||
|
||
keyBuf = ByteBuffer.allocateDirect(keySize); | ||
valueBuf = ByteBuffer.allocateDirect(valueSize); | ||
Arrays.fill(keyArr, (byte) 0x30); | ||
Arrays.fill(valueArr, (byte) 0x30); | ||
keyBuf.put(keyArr); | ||
keyBuf.flip(); | ||
valueBuf.put(valueArr); | ||
valueBuf.flip(); | ||
} | ||
|
||
@TearDown(Level.Trial) | ||
|
@@ -93,13 +120,14 @@ public void cleanup() throws IOException { | |
} | ||
db.close(); | ||
options.close(); | ||
readOptions.close(); | ||
FileUtils.delete(dbDir); | ||
} | ||
|
||
private ColumnFamilyHandle getColumnFamily() { | ||
if (cfs == 0) { | ||
return cfHandles[0]; | ||
} else if (cfs == 1) { | ||
} else if (cfs == 1) { | ||
return cfHandles[1]; | ||
} else { | ||
int idx = cfHandlesIdx.getAndIncrement(); | ||
|
@@ -131,9 +159,70 @@ private int next() { | |
return idx; | ||
} | ||
|
||
@Benchmark | ||
public byte[] get() throws RocksDBException { | ||
// String -> byte[] | ||
private byte[] getKeyArr() { | ||
final int MAX_LEN = 9; // key100000 | ||
final int keyIdx = next(); | ||
return db.get(getColumnFamily(), ba("key" + keyIdx)); | ||
final byte[] keyPrefix = ba("key" + keyIdx); | ||
System.arraycopy(keyPrefix, 0, keyArr, 0, keyPrefix.length); | ||
Arrays.fill(keyArr, keyPrefix.length, MAX_LEN, (byte) 0x30); | ||
return keyArr; | ||
} | ||
|
||
// String -> ByteBuffer | ||
private ByteBuffer getKeyBuf() { | ||
final int MAX_LEN = 9; // key100000 | ||
final int keyIdx = next(); | ||
final String keyStr = "key" + keyIdx; | ||
for (int i = 0; i < keyStr.length(); ++i) { | ||
keyBuf.put(i, (byte) keyStr.charAt(i)); | ||
} | ||
for (int i = keyStr.length(); i < MAX_LEN; ++i) { | ||
keyBuf.put(i, (byte) 0x30); | ||
} | ||
// Reset position for future reading | ||
keyBuf.position(0); | ||
return keyBuf; | ||
} | ||
|
||
private byte[] getValueArr() { | ||
return valueArr; | ||
} | ||
|
||
private ByteBuffer getValueBuf() { | ||
return valueBuf; | ||
} | ||
|
||
@Benchmark | ||
public void get() throws RocksDBException { | ||
db.get(getColumnFamily(), getKeyArr()); | ||
} | ||
|
||
@Benchmark | ||
public void preallocatedGet() throws RocksDBException { | ||
db.get(getColumnFamily(), getKeyArr(), getValueArr()); | ||
} | ||
|
||
@Benchmark | ||
public void preallocatedCriticalGet() throws RocksDBException { | ||
db.getCritical(getColumnFamily(), getKeyArr(), getValueArr()); | ||
} | ||
|
||
@Benchmark | ||
public void preallocatedByteBufferGet() throws RocksDBException { | ||
int res = db.get(getColumnFamily(), readOptions, getKeyBuf(), getValueBuf()); | ||
// For testing correctness: | ||
// assert res > 0; | ||
// final byte[] ret = new byte[valueSize]; | ||
// valueBuf.get(ret); | ||
// System.out.println(str(ret)); | ||
// valueBuf.flip(); | ||
Comment on lines
+214
to
+219
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remove the unused code? |
||
} | ||
|
||
@Benchmark | ||
public void unsafeGet() throws RocksDBException { | ||
PinnableSlice pinnableSlice = db.getUnsafe(getColumnFamily(), readOptions, getKeyArr()); | ||
// assert pinnableSlice.capacity() > 0; | ||
pinnableSlice.close(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#include "include/org_rocksdb_PinnableSlice.h" | ||
#include "rocksdb/slice.h" | ||
|
||
/* | ||
* Class: org_rocksdb_PinnableSlice | ||
* Method: deletePinnableSlice | ||
* Signature: (J)V | ||
*/ | ||
void Java_org_rocksdb_PinnableSlice_deletePinnableSlice(JNIEnv*, jclass, | ||
jlong handle) { | ||
auto* pinnable_slice = | ||
reinterpret_cast<ROCKSDB_NAMESPACE::PinnableSlice*>(handle); | ||
assert(pinnable_slice != nullptr); | ||
pinnable_slice->Reset(); | ||
delete pinnable_slice; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. expect blank line here |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems this test has the best throughput