Skip to content
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

JNI get_helper code sharing / multiGet() use efficient batch C++ support [replaced by https://github.com/facebook/rocksdb/pull/12344] #11827

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
25aacb2
Replace jbyteArray rocksdb_get_helper with shared
alanpaxton Sep 13, 2023
b5d8cea
Overload txn::GetForUpdate w/ PinnableSlice
alanpaxton Sep 13, 2023
85024c1
Move other rocksjni get helper to new pattern.
alanpaxton Sep 13, 2023
f22d52b
format fixes
alanpaxton Sep 13, 2023
6adba4e
Distinguish overloaded Transaction::GetForUpdate
alanpaxton Sep 18, 2023
bbabfbc
Further disambiguation of overloaded GetForUpdate
alanpaxton Sep 18, 2023
5c1e0e7
fat fingers put rubbish in CMakeLists - repair
alanpaxton Sep 18, 2023
d626551
Convert MultiGet to RAII, removing helpers
alanpaxton Sep 19, 2023
f26271e
Perf test first refactored jni multiGet function
alanpaxton Sep 20, 2023
0f6809e
Tidy up obsolete code after testing
alanpaxton Sep 26, 2023
af8f0eb
All jni_get_helpers MultiGetKeys methods static
alanpaxton Sep 26, 2023
a23c6ad
Ah no, static doesn’t work
alanpaxton Sep 26, 2023
7c8e86a
Convert multiGet with CF list to RAII
alanpaxton Sep 27, 2023
291f016
RAII-ify more rocksjni.cc multiGet()s - not direct
alanpaxton Sep 27, 2023
3642a54
Convert multiGet ByteBuffer version to RAII
alanpaxton Sep 27, 2023
c9c9c4c
Add `slices()` method to keys class in jni_get_helpers
alanpaxton Oct 2, 2023
746d090
Remove obsoleted support method
alanpaxton Oct 2, 2023
fb2bb1e
Fix typos
alanpaxton Oct 2, 2023
6afc589
Efficient multiGet() invalidates a test assumption
alanpaxton Oct 2, 2023
3772612
Forgot to fix formatting
alanpaxton Oct 2, 2023
bb426cb
Modernize jni multiGet and multiGetForUpdate
alanpaxton Oct 4, 2023
d0ba2c5
Extend/update jni multiGet benchmarks
alanpaxton Oct 4, 2023
bf3dd5b
Add multiget across random CFs jmh test
alanpaxton Oct 4, 2023
d8f806b
Start to remove/replace jni_get_helper()
alanpaxton Oct 5, 2023
6758314
Completely replace jbyteArray jni_get_helper
alanpaxton Oct 5, 2023
efe2f26
Replace jint jni_get_helper
alanpaxton Oct 6, 2023
1d3227e
convert raw to unique_ptr in JNI get keys helper
alanpaxton Oct 6, 2023
daa1171
Code comment new JNI get/multiGet helpers
alanpaxton Oct 9, 2023
b986780
Replace JNI method rocksdb_get_helper_direct
alanpaxton Oct 9, 2023
95f75bf
RAII get helpers final polish - naming, cleanup
alanpaxton Oct 11, 2023
99a3420
Fix get() class that rebase got wrong.
alanpaxton Jan 9, 2024
70fe6e5
getDirect() Replace GetJNIKey / GetJNIValue helpers
alanpaxton Jan 9, 2024
74b1d95
Re-instate getDirect() lost in rebase
alanpaxton Jan 9, 2024
7f6c121
Replace ::GetJNIKey / ::GetJNIValue w/
alanpaxton Jan 10, 2024
695098a
Rename helper file now with only multiget code
alanpaxton Jan 10, 2024
addff1e
Update jmh instructions
alanpaxton Jan 10, 2024
efeb4d2
Test Java API MultiGet with big (overflow) reads
alanpaxton Jan 16, 2024
3f72f6f
Remove obsolete definition
alanpaxton Jan 16, 2024
bc26fde
Add a history entry for Java MultiGet performance
alanpaxton Jan 17, 2024
102e86b
Ignore big put edge case tests which are slow
alanpaxton Jan 22, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions include/rocksdb/utilities/transaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,23 @@ class Transaction {
std::string* value, bool exclusive = true,
const bool do_validate = true) = 0;

// An overload of the above method that receives a PinnableSlice
// For backward compatibility a default implementation is provided
virtual Status GetForUpdate(const ReadOptions& options, const Slice& key,
PinnableSlice* pinnable_val,
bool exclusive = true,
const bool do_validate = true) {
if (pinnable_val == nullptr) {
std::string* null_str = nullptr;
return GetForUpdate(options, key, null_str, exclusive, do_validate);
} else {
auto s = GetForUpdate(options, key, pinnable_val->GetSelf(), exclusive,
do_validate);
pinnable_val->PinSelf();
return s;
}
}

virtual std::vector<Status> MultiGetForUpdate(
const ReadOptions& options,
const std::vector<ColumnFamilyHandle*>& column_family,
Expand Down
1 change: 1 addition & 0 deletions java/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ set(JNI_NATIVE_SOURCES
rocksjni/hyper_clock_cache.cc
rocksjni/ingest_external_file_options.cc
rocksjni/iterator.cc
rocksjni/jni_multiget_helpers.cc
rocksjni/jnicallback.cc
rocksjni/loggerjnicallback.cc
rocksjni/lru_cache.cc
Expand Down
4 changes: 2 additions & 2 deletions java/jmh/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ These are micro-benchmarks for RocksJava functionality, using [JMH (Java Microbe

**Note**: This uses a specific build of RocksDB that is set in the `<version>` element of the `dependencies` section of the `pom.xml` file. If you are testing local changes you should build and install a SNAPSHOT version of rocksdbjni, and update the `pom.xml` of rocksdbjni-jmh file to test with this.

For instance, this is how to install the OSX jar you just built for 6.26.0
For instance, this is how to install the OSX jar you just built for 8.11.0

```bash
$ mvn install:install-file -Dfile=./java/target/rocksdbjni-6.26.0-SNAPSHOT-osx.jar -DgroupId=org.rocksdb -DartifactId=rocksdbjni -Dversion=6.26.0-SNAPSHOT -Dpackaging=jar
$ mvn install:install-file -Dfile=./java/target/rocksdbjni-8.11.0-SNAPSHOT-osx.jar -DgroupId=org.rocksdb -DartifactId=rocksdbjni -Dversion=8.11.0-SNAPSHOT -Dpackaging=jar
```

```bash
Expand Down
6 changes: 3 additions & 3 deletions java/jmh/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@
</scm>

<properties>
<project.build.source>1.7</project.build.source>
<project.build.target>1.7</project.build.target>
<project.build.source>17</project.build.source>
<project.build.target>17</project.build.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

<jmh.version>1.22</jmh.version>
Expand All @@ -50,7 +50,7 @@
<dependency>
<groupId>org.rocksdb</groupId>
<artifactId>rocksdbjni</artifactId>
<version>7.9.0-SNAPSHOT</version>
<version>8.11.0</version>
</dependency>

<dependency>
Expand Down
77 changes: 71 additions & 6 deletions java/jmh/src/main/java/org/rocksdb/jmh/MultiGetBenchmarks.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ public class MultiGetBenchmarks {
RocksDB db;
private final AtomicInteger keyIndex = new AtomicInteger();

private List<ColumnFamilyHandle> defaultCFHandles = new ArrayList<>();
private List<ColumnFamilyHandle> randomCFHandles = new ArrayList<>();

@Setup(Level.Trial)
public void setup() throws IOException, RocksDBException {
RocksDB.loadLibrary();
Expand Down Expand Up @@ -88,13 +91,30 @@ public void setup() throws IOException, RocksDBException {
cfHandles = cfHandlesList.toArray(new ColumnFamilyHandle[0]);

// store initial data for retrieving via get
for (int j = 0; j < keyCount; j++) {
final byte[] paddedValue = Arrays.copyOf(ba("value" + j), valueSize);
db.put(ba("key" + j), paddedValue);
}

// store initial data for retrieving via get - column families
for (int i = 0; i < cfs; i++) {
for (int j = 0; j < keyCount; j++) {
final byte[] paddedValue = Arrays.copyOf(ba("value" + j), valueSize);
db.put(cfHandles[i], ba("key" + j), paddedValue);
}
}

// build a big list of default column families for efficient passing
final ColumnFamilyHandle defaultCFH = db.getDefaultColumnFamily();
for (int i = 0; i < keyCount; i++) {
defaultCFHandles.add(defaultCFH);
}

// list of random cfs
for (int i = 0; i < keyCount; i++) {
randomCFHandles.add(cfHandlesList.get((int) (Math.random() * cfs)));
}

try (final FlushOptions flushOptions = new FlushOptions()
.setWaitForFlush(true)) {
db.flush(flushOptions);
Expand Down Expand Up @@ -163,15 +183,13 @@ private int next(final int inc, final int limit) {

@Setup
public void allocateSliceBuffers() {
keysBuffer = ByteBuffer.allocateDirect(keyCount * valueSize);
keysBuffer = ByteBuffer.allocateDirect(keyCount * keySize);
valuesBuffer = ByteBuffer.allocateDirect(keyCount * valueSize);
valueBuffersList = new ArrayList<>();
keyBuffersList = new ArrayList<>();
for (int i = 0; i < keyCount; i++) {
valueBuffersList.add(valuesBuffer.slice());
valuesBuffer.position(i * valueSize);
keyBuffersList.add(keysBuffer.slice());
keysBuffer.position(i * keySize);
valueBuffersList.add(valuesBuffer.slice(i * valueSize, valueSize));
keyBuffersList.add(keysBuffer.slice(i * keySize, keySize));
}
}

Expand All @@ -181,7 +199,7 @@ public void freeSliceBuffers() {
}

@Benchmark
public List<byte[]> multiGet10() throws RocksDBException {
public void multiGetList10() throws RocksDBException {
final int fromKeyIdx = next(multiGetSize, keyCount);
if (fromKeyIdx >= 0) {
final List<byte[]> keys = keys(fromKeyIdx, fromKeyIdx + multiGetSize);
Expand All @@ -191,6 +209,53 @@ public List<byte[]> multiGet10() throws RocksDBException {
throw new RuntimeException("Test valueSize assumption wrong");
}
}
}

@Benchmark
public void multiGetListExplicitCF20() throws RocksDBException {
final int fromKeyIdx = next(multiGetSize, keyCount);
if (fromKeyIdx >= 0) {
final List<byte[]> keys = keys(fromKeyIdx, fromKeyIdx + multiGetSize);
final List<ColumnFamilyHandle> columnFamilyHandles =
defaultCFHandles.subList(fromKeyIdx, fromKeyIdx + multiGetSize);
final List<byte[]> valueResults = db.multiGetAsList(columnFamilyHandles, keys);
for (final byte[] result : valueResults) {
if (result.length != valueSize)
throw new RuntimeException("Test valueSize assumption wrong");
}
}
}

@Benchmark
public void multiGetListRandomCF30() throws RocksDBException {
final int fromKeyIdx = next(multiGetSize, keyCount);
if (fromKeyIdx >= 0) {
final List<byte[]> keys = keys(fromKeyIdx, fromKeyIdx + multiGetSize);
final List<ColumnFamilyHandle> columnFamilyHandles =
randomCFHandles.subList(fromKeyIdx, fromKeyIdx + multiGetSize);
final List<byte[]> valueResults = db.multiGetAsList(columnFamilyHandles, keys);
for (final byte[] result : valueResults) {
if (result.length != valueSize)
throw new RuntimeException("Test valueSize assumption wrong");
}
}
}

@Benchmark
public List<byte[]> multiGetBB200() throws RocksDBException {
final int fromKeyIdx = next(multiGetSize, keyCount);
if (fromKeyIdx >= 0) {
final List<ByteBuffer> keys = keys(keyBuffersList, fromKeyIdx, fromKeyIdx + multiGetSize);
final List<ByteBuffer> values =
valueBuffersList.subList(fromKeyIdx, fromKeyIdx + multiGetSize);
final List<ByteBufferGetStatus> statusResults = db.multiGetByteBuffers(keys, values);
for (final ByteBufferGetStatus result : statusResults) {
if (result.status.getCode() != Status.Code.Ok)
throw new RuntimeException("Test status not OK: " + result.status);
if (result.value.limit() != valueSize)
throw new RuntimeException("Test valueSize assumption wrong");
}
}
return new ArrayList<>();
}

Expand Down
Loading
Loading