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

Java Panama FFI prototype experiments (DO NOT MERGE) #11095

Draft
wants to merge 55 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
72b5295
Panama FFI experiments - WIP
alanpaxton Dec 30, 2022
50e7250
Continue to prototype Panama - basic get() working
alanpaxton Jan 9, 2023
772a8fe
Refactor after proving basic get() implementation
alanpaxton Jan 10, 2023
f3a8faa
Add variant methods and comments
alanpaxton Jan 10, 2023
0f5aa4b
Add JMH benchmarks for new FFI-based methods
alanpaxton Jan 10, 2023
3e83aa4
Improve exception handling in get()
alanpaxton Jan 11, 2023
e580d13
FFI - Use an implicit memory session
alanpaxton Jan 11, 2023
299be7a
Add another benchmark, start some documentation.
alanpaxton Jan 11, 2023
8afd0f3
Refactor tests, add a bulk test, comments
alanpaxton Jan 11, 2023
664c953
Silly bugs, check fixes
alanpaxton Jan 11, 2023
c2af0b1
Remove commented out line, reset java tests
alanpaxton Jan 12, 2023
1a2487d
More descriptive text, initial results
alanpaxton Jan 12, 2023
aba7627
Add black holes to java jmh GetBenchmark.
alanpaxton Jan 12, 2023
a45d14d
missed random preallocated old-style get() bench
alanpaxton Jan 12, 2023
dab7782
script for next benchmark attempt
alanpaxton Jan 12, 2023
1734dec
Further documentation
alanpaxton Jan 12, 2023
3a559ac
getOutputSlice operation/tests
alanpaxton Jan 16, 2023
629a092
Custom fast allocation for benchmarking
alanpaxton Jan 17, 2023
a57bd41
Remove some logging
alanpaxton Jan 17, 2023
9378075
Add our benchmark result directory, temporarily
alanpaxton Jan 17, 2023
c8f8fec
Current version of living markdown document
alanpaxton Jan 17, 2023
4c19a51
Add explicit readoptions param, null test
alanpaxton Jan 23, 2023
cf84e91
Finalize blog post/report.
alanpaxton Jan 23, 2023
d600ce9
Reduce allocation count of getPinnableSlice
alanpaxton Jan 23, 2023
0100130
Surface MemorySegments as parameters
alanpaxton Jan 23, 2023
f28a1da
Debug non-deletion of db in test
alanpaxton Jan 24, 2023
7f05595
Return to standard allocator
alanpaxton Jan 24, 2023
22d37c2
Remove some logging
alanpaxton Jan 24, 2023
d22430f
Latest results, better graph
alanpaxton Jan 24, 2023
531ae0b
Try not to free/allocate pinnable slice
alanpaxton Jan 24, 2023
2dac2ba
Access via VarHandle(s) is slow ??
alanpaxton Jan 24, 2023
d8a2447
Cleanup
alanpaxton Jan 25, 2023
afaef4f
Comments on allocation in getOutputSlice
alanpaxton Jan 25, 2023
fd1c11b
Clean up superfluous benchmark runs
alanpaxton Jan 25, 2023
c147a81
Remove irrelevant stuff from benchmarks
alanpaxton Jan 25, 2023
f4d558a
invokedExact instead of invoke
alanpaxton Jan 25, 2023
8e0d0a8
New final run set of results
alanpaxton Jan 26, 2023
3b58ba3
Update/polish report document
alanpaxton Jan 26, 2023
bc593a1
Update version for jmh README
alanpaxton Mar 9, 2023
5b85b4e
final MethodHandles for performance
alanpaxton Mar 9, 2023
6b5da67
Avoid extra allocation of memory segment
alanpaxton Mar 9, 2023
9279e85
Format and remove unused imports
alanpaxton Mar 9, 2023
50fd059
Update POM, improve README build instructions
alanpaxton Mar 9, 2023
a1f158f
Check exact invocation
alanpaxton Mar 13, 2023
e5b63e3
Fix inexact FFI invocations
alanpaxton Mar 13, 2023
6633c44
Revert "Check exact invocation"
alanpaxton Mar 13, 2023
e967010
Make inexact invocation exact
alanpaxton Mar 13, 2023
1395c33
Avoid unnecessary buffer creation
alanpaxton Mar 13, 2023
f7ec395
fix format
alanpaxton Mar 13, 2023
3cfdbe5
Quick canned build/run script
alanpaxton Mar 13, 2023
73a2c89
More generic script
alanpaxton Mar 13, 2023
b996c30
Update performance numbers and report
alanpaxton Mar 16, 2023
3e91558
Compare pin/release to copy
alanpaxton Mar 20, 2023
74530ae
Allow png,pdf as they are included in our markdown
alanpaxton Mar 20, 2023
ba0b75e
Replace std::string w/ SliceBuffer
alanpaxton Mar 20, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions Makefile
Expand Up @@ -291,6 +291,9 @@ endif
export JAVAC_ARGS
CLEAN_FILES += make_config.mk rocksdb.pc

export JAVA_ARGS
export JAVADOC_ARGS

ifeq ($(V), 1)
$(info $(shell uname -a))
$(info $(shell $(CC) --version))
Expand Down
6 changes: 5 additions & 1 deletion build_tools/build_detect_platform
Expand Up @@ -269,7 +269,9 @@ esac
PLATFORM_CXXFLAGS="$PLATFORM_CXXFLAGS ${CXXFLAGS}"
JAVA_LDFLAGS="$PLATFORM_LDFLAGS"
JAVA_STATIC_LDFLAGS="$PLATFORM_LDFLAGS"
JAVAC_ARGS="-source 8"
JAVAC_ARGS="-source 19 --enable-preview -Xlint:preview"
JAVA_ARGS="--enable-preview --enable-native-access=ALL-UNNAMED"
JAVADOC_ARGS="-source 19 --enable-preview"

if [ "$CROSS_COMPILE" = "true" -o "$FBCODE_BUILD" = "true" ]; then
# Cross-compiling; do not try any compilation tests.
Expand Down Expand Up @@ -867,6 +869,8 @@ echo "JAVA_STATIC_DEPS_CCFLAGS=$JAVA_STATIC_DEPS_CCFLAGS" >> "$OUTPUT"
echo "JAVA_STATIC_DEPS_CXXFLAGS=$JAVA_STATIC_DEPS_CXXFLAGS" >> "$OUTPUT"
echo "JAVA_STATIC_DEPS_LDFLAGS=$JAVA_STATIC_DEPS_LDFLAGS" >> "$OUTPUT"
echo "JAVAC_ARGS=$JAVAC_ARGS" >> "$OUTPUT"
echo "JAVA_ARGS=$JAVA_ARGS" >> "$OUTPUT"
echo "JAVADOC_ARGS=$JAVADOC_ARGS" >> "$OUTPUT"
echo "VALGRIND_VER=$VALGRIND_VER" >> "$OUTPUT"
echo "PLATFORM_CCFLAGS=$PLATFORM_CCFLAGS" >> "$OUTPUT"
echo "PLATFORM_CXXFLAGS=$PLATFORM_CXXFLAGS" >> "$OUTPUT"
Expand Down
2 changes: 1 addition & 1 deletion build_tools/check-sources.sh
Expand Up @@ -37,7 +37,7 @@ if [ "$?" != "1" ]; then
BAD=1
fi

git grep -n -P "[\x80-\xFF]" -- ':!docs' ':!*.md'
git grep -n -P "[\x80-\xFF]" -- ':!docs' ':!*.md' '!*.png' '!*.pdf'
if [ "$?" != "1" ]; then
echo '^^^^ Use only ASCII characters in source files'
BAD=1
Expand Down
2 changes: 1 addition & 1 deletion db/c.cc
Expand Up @@ -5763,7 +5763,7 @@ rocksdb_pinnableslice_t* rocksdb_transaction_get_pinned_for_update(
const char* key, size_t klen, unsigned char exclusive, char** errptr) {
rocksdb_pinnableslice_t* v = new (rocksdb_pinnableslice_t);
Status s = txn->rep->GetForUpdate(options->rep, Slice(key, klen),
v->rep.GetSelf(), exclusive);
v->rep.GetSelf()->String(), exclusive);
v->rep.PinSelf();
if (!s.ok()) {
delete (v);
Expand Down
19 changes: 10 additions & 9 deletions db/db_impl/db_impl.cc
Expand Up @@ -2109,14 +2109,15 @@ Status DBImpl::GetImpl(const ReadOptions& read_options, const Slice& key,
if (!skip_memtable) {
// Get value associated with key
if (get_impl_options.get_value) {
if (sv->mem->Get(
lkey,
get_impl_options.value ? get_impl_options.value->GetSelf()
: nullptr,
get_impl_options.columns, timestamp, &s, &merge_context,
&max_covering_tombstone_seq, read_options,
false /* immutable_memtable */, get_impl_options.callback,
get_impl_options.is_blob_index)) {
if (sv->mem->Get(lkey,
get_impl_options.value
? get_impl_options.value->GetSelf()->String()
: nullptr,
get_impl_options.columns, timestamp, &s, &merge_context,
&max_covering_tombstone_seq, read_options,
false /* immutable_memtable */,
get_impl_options.callback,
get_impl_options.is_blob_index)) {
done = true;

if (get_impl_options.value) {
Expand All @@ -2127,7 +2128,7 @@ Status DBImpl::GetImpl(const ReadOptions& read_options, const Slice& key,
} else if ((s.ok() || s.IsMergeInProgress()) &&
sv->imm->Get(lkey,
get_impl_options.value
? get_impl_options.value->GetSelf()
? get_impl_options.value->GetSelf()->String()
: nullptr,
get_impl_options.columns, timestamp, &s,
&merge_context, &max_covering_tombstone_seq,
Expand Down
2 changes: 1 addition & 1 deletion db/db_impl/db_impl_readonly.cc
Expand Up @@ -84,7 +84,7 @@ Status DBImplReadOnly::Get(const ReadOptions& read_options,
SequenceNumber max_covering_tombstone_seq = 0;
LookupKey lkey(key, snapshot, read_options.timestamp);
PERF_TIMER_STOP(get_snapshot_time);
if (super_version->mem->Get(lkey, pinnable_val->GetSelf(),
if (super_version->mem->Get(lkey, pinnable_val->GetSelf()->String(),
/*columns=*/nullptr, ts, &s, &merge_context,
&max_covering_tombstone_seq, read_options,
false /* immutable_memtable */, &read_cb)) {
Expand Down
8 changes: 4 additions & 4 deletions db/db_impl/db_impl_secondary.cc
Expand Up @@ -392,7 +392,7 @@ Status DBImplSecondary::GetImpl(const ReadOptions& read_options,
const Comparator* ucmp = column_family->GetComparator();
assert(ucmp);
std::string* ts = ucmp->timestamp_size() > 0 ? timestamp : nullptr;
if (super_version->mem->Get(lkey, pinnable_val->GetSelf(),
if (super_version->mem->Get(lkey, pinnable_val->GetSelf()->String(),
/*columns=*/nullptr, ts, &s, &merge_context,
&max_covering_tombstone_seq, read_options,
false /* immutable_memtable */, &read_cb)) {
Expand All @@ -401,9 +401,9 @@ Status DBImplSecondary::GetImpl(const ReadOptions& read_options,
RecordTick(stats_, MEMTABLE_HIT);
} else if ((s.ok() || s.IsMergeInProgress()) &&
super_version->imm->Get(
lkey, pinnable_val->GetSelf(), /*columns=*/nullptr, ts, &s,
&merge_context, &max_covering_tombstone_seq, read_options,
&read_cb)) {
lkey, pinnable_val->GetSelf()->String(), /*columns=*/nullptr,
ts, &s, &merge_context, &max_covering_tombstone_seq,
read_options, &read_cb)) {
done = true;
pinnable_val->PinSelf();
RecordTick(stats_, MEMTABLE_HIT);
Expand Down
7 changes: 4 additions & 3 deletions db/memtable.cc
Expand Up @@ -1455,9 +1455,10 @@ void MemTable::MultiGet(const ReadOptions& read_options, MultiGetRange* range,
SequenceNumber dummy_seq;
GetFromTable(*(iter->lkey), iter->max_covering_tombstone_seq, true,
callback, &iter->is_blob_index,
iter->value ? iter->value->GetSelf() : nullptr, iter->columns,
iter->timestamp, iter->s, &(iter->merge_context), &dummy_seq,
&found_final_value, &merge_in_progress);
iter->value ? iter->value->GetSelf()->String() : nullptr,
iter->columns, iter->timestamp, iter->s,
&(iter->merge_context), &dummy_seq, &found_final_value,
&merge_in_progress);

if (!found_final_value && merge_in_progress) {
*(iter->s) = Status::MergeInProgress();
Expand Down
4 changes: 2 additions & 2 deletions db/version_set.cc
Expand Up @@ -2440,7 +2440,7 @@ void Version::Get(const ReadOptions& read_options, const LookupKey& k,
/* op_failure_scope */ nullptr);
if (status->ok()) {
if (LIKELY(value != nullptr)) {
*(value->GetSelf()) = std::move(result);
*(value->GetSelf()->String()) = std::move(result);
value->PinSelf();
} else {
assert(columns != nullptr);
Expand Down Expand Up @@ -2690,7 +2690,7 @@ void Version::MultiGet(const ReadOptions& read_options, MultiGetRange* range,
/* result_operand */ nullptr, /* update_num_ops_stats */ true,
/* op_failure_scope */ nullptr);
if (LIKELY(iter->value != nullptr)) {
*iter->value->GetSelf() = std::move(result);
*iter->value->GetSelf()->String() = std::move(result);
iter->value->PinSelf();
range->AddValueSize(iter->value->size());
} else {
Expand Down
35 changes: 24 additions & 11 deletions include/rocksdb/slice.h
Expand Up @@ -129,6 +129,19 @@ class Slice {
// Intentionally copyable
};

class SliceBuffer {
public:
inline std::string* String() { return buf_; }
SliceBuffer& operator=(std::string* buf) {
this->buf_ = buf;
return *this;
}

private:
friend class PinnableSlice;
std::string* buf_;
};

/**
* A Slice that can be pinned with some cleanup tasks, which will be run upon
* ::Reset() or object destruction, whichever is invoked first. This can be used
Expand All @@ -137,8 +150,8 @@ class Slice {
*/
class PinnableSlice : public Slice, public Cleanable {
public:
PinnableSlice() { buf_ = &self_space_; }
explicit PinnableSlice(std::string* buf) { buf_ = buf; }
PinnableSlice() { slice_buffer_ = &self_space_; }
explicit PinnableSlice(std::string* buf) { slice_buffer_ = buf; }

PinnableSlice(PinnableSlice&& other);
PinnableSlice& operator=(PinnableSlice&& other);
Expand Down Expand Up @@ -170,16 +183,16 @@ class PinnableSlice : public Slice, public Cleanable {

inline void PinSelf(const Slice& slice) {
assert(!pinned_);
buf_->assign(slice.data(), slice.size());
data_ = buf_->data();
size_ = buf_->size();
slice_buffer_.buf_->assign(slice.data(), slice.size());
data_ = slice_buffer_.buf_->data();
size_ = slice_buffer_.buf_->size();
assert(!pinned_);
}

inline void PinSelf() {
assert(!pinned_);
data_ = buf_->data();
size_ = buf_->size();
data_ = slice_buffer_.buf_->data();
size_ = slice_buffer_.buf_->size();
assert(!pinned_);
}

Expand All @@ -188,7 +201,7 @@ class PinnableSlice : public Slice, public Cleanable {
if (pinned_) {
size_ -= n;
} else {
buf_->erase(size() - n, n);
slice_buffer_.buf_->erase(size() - n, n);
PinSelf();
}
}
Expand All @@ -199,7 +212,7 @@ class PinnableSlice : public Slice, public Cleanable {
data_ += n;
size_ -= n;
} else {
buf_->erase(0, n);
slice_buffer_.buf_->erase(0, n);
PinSelf();
}
}
Expand All @@ -210,14 +223,14 @@ class PinnableSlice : public Slice, public Cleanable {
size_ = 0;
}

inline std::string* GetSelf() { return buf_; }
inline SliceBuffer* GetSelf() { return &slice_buffer_; }

inline bool IsPinned() const { return pinned_; }

private:
friend class PinnableSlice4Test;
std::string self_space_;
std::string* buf_;
SliceBuffer slice_buffer_;
bool pinned_ = false;
};

Expand Down
8 changes: 5 additions & 3 deletions include/rocksdb/utilities/transaction.h
Expand Up @@ -301,7 +301,8 @@ class Transaction {
ColumnFamilyHandle* column_family, const Slice& key,
PinnableSlice* pinnable_val) {
assert(pinnable_val != nullptr);
auto s = Get(options, column_family, key, pinnable_val->GetSelf());
auto s =
Get(options, column_family, key, pinnable_val->GetSelf()->String());
pinnable_val->PinSelf();
return s;
}
Expand All @@ -311,7 +312,7 @@ class Transaction {
virtual Status Get(const ReadOptions& options, const Slice& key,
PinnableSlice* pinnable_val) {
assert(pinnable_val != nullptr);
auto s = Get(options, key, pinnable_val->GetSelf());
auto s = Get(options, key, pinnable_val->GetSelf()->String());
pinnable_val->PinSelf();
return s;
}
Expand Down Expand Up @@ -385,7 +386,8 @@ class Transaction {
do_validate);
} else {
auto s = GetForUpdate(options, column_family, key,
pinnable_val->GetSelf(), exclusive, do_validate);
pinnable_val->GetSelf()->String(), exclusive,
do_validate);
pinnable_val->PinSelf();
return s;
}
Expand Down
2 changes: 1 addition & 1 deletion include/rocksdb/wide_columns.h
Expand Up @@ -139,7 +139,7 @@ inline void PinnableWideColumns::MoveValue(PinnableSlice&& value) {
}

inline void PinnableWideColumns::MoveValue(std::string&& value) {
std::string* const buf = value_.GetSelf();
std::string* const buf = value_.GetSelf()->String();
assert(buf);

*buf = std::move(value);
Expand Down
25 changes: 17 additions & 8 deletions java/GetBenchmarks.md
Expand Up @@ -5,31 +5,40 @@ Results associated with [Improve Java API `get()` performance by reducing copies
## Build/Run

Mac
```
```bash
make clean jclean
DEBUG_LEVEL=0 make -j12 rocksdbjava
(cd java/target; cp rocksdbjni-7.9.0-osx.jar rocksdbjni-7.9.0-SNAPSHOT-osx.jar)
mvn install:install-file -Dfile=./java/target/rocksdbjni-7.9.0-SNAPSHOT-osx.jar -DgroupId=org.rocksdb -DartifactId=rocksdbjni -Dversion=7.9.0-SNAPSHOT -Dpackaging=jar
(cd java/target; cp rocksdbjni-7.10.0-osx.jar rocksdbjni-7.10.0-SNAPSHOT-osx.jar)
mvn install:install-file -Dfile=./java/target/rocksdbjni-7.10.0-SNAPSHOT-osx.jar -DgroupId=org.rocksdb -DartifactId=rocksdbjni -Dversion=7.10.0-SNAPSHOT -Dpackaging=jar
```

Linux
```
```bash
make clean jclean
DEBUG_LEVEL=0 make -j12 rocksdbjava
(cd java/target; cp rocksdbjni-7.9.0-linux64.jar rocksdbjni-7.9.0-SNAPSHOT-linux64.jar)
mvn install:install-file -Dfile=./java/target/rocksdbjni-7.9.0-SNAPSHOT-linux64.jar -DgroupId=org.rocksdb -DartifactId=rocksdbjni -Dversion=7.9.0-SNAPSHOT -Dpackaging=jar
(cd java/target; cp rocksdbjni-7.10.0-linux64.jar rocksdbjni-7.10.0-SNAPSHOT-linux64.jar)
mvn install:install-file -Dfile=./java/target/rocksdbjni-7.10.0-SNAPSHOT-linux64.jar -DgroupId=org.rocksdb -DartifactId=rocksdbjni -Dversion=7.10.0-SNAPSHOT -Dpackaging=jar
```

Build jmh test package, on either platform
```
```bash
pushd java/jmh
mvn clean package
```

A quick test run, just as a sanity check, using a small number of keys, would be
```
```bash
java -jar target/rocksdbjni-jmh-1.0-SNAPSHOT-benchmarks.jar -p keyCount=1000 -p keySize=128 -p valueSize=32768 -p columnFamilyTestType="no_column_family" GetBenchmarks
```
or when we are previewing new features (e.g. Panama FFI in Java 19)
```bash
java --enable-preview --enable-native-access=ALL-UNNAMED -jar target/rocksdbjni-jmh-1.0-SNAPSHOT-benchmarks.jar -p keyCount=1000 -p keySize=128 -p valueSize=32768 -p columnFamilyTestType="no_column_family" GetBenchmarks
```
to reduce the time to an absolute minimum, append these parameters
```bash
-wi 1 -to 1m -i 1
```

The long performance run (as big as we can make it on our Ubuntu box without filling the disk)
```
java -jar target/rocksdbjni-jmh-1.0-SNAPSHOT-benchmarks.jar -p keyCount=1000,50000 -p keySize=128 -p valueSize=1024,16384 -p columnFamilyTestType="1_column_family","20_column_families" GetBenchmarks.get GetBenchmarks.preallocatedByteBufferGet GetBenchmarks.preallocatedGet
Expand Down