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

Extend Java RocksDB iterators to support indirect Byte Buffers #9222

Closed

Conversation

alanpaxton
Copy link
Contributor

@alanpaxton alanpaxton commented Nov 29, 2021

Extend Java RocksDB iterators to support indirect byte buffers, to add to the existing support for direct byte buffers.
Code to distinguish direct/indirect buffers is switched in Java, and a 2nd separate JNI call implemented to support indirect
buffers. Indirect support passes contained buffers using byte[]

There are some Java subclasses of iterator (WBWIIterator, SstFileReaderIterator) which also now have parallel JNI support functions implemented, along with direct/indirect switches in Java methods.

Closes #6282

@adamretter adamretter changed the title Fb 6282 java iterator bb extension Extend Java RocksDB iterators to support indirect Byte Buffers Nov 29, 2021
@adamretter adamretter self-requested a review November 29, 2021 13:28
Copy link
Collaborator

@adamretter adamretter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM :-)
Thanks @alanpaxton

jint jkey_len) {
auto* it = reinterpret_cast<ROCKSDB_NAMESPACE::Iterator*>(handle);
ROCKSDB_NAMESPACE::Slice key_slice = it->key();
jsize copy_size = std::min(static_cast<uint32_t>(key_slice.size()),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

define var actual_size=key_slice.size()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've done auto slice_size = key_slice.size(); ? (actual suggests to me the presence of non-actual).

jkey, jkey_off, copy_size,
const_cast<jbyte*>(reinterpret_cast<const jbyte*>(key_slice.data())));

return static_cast<jsize>(key_slice.size());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can use actual_size here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

slice_size

jint jvalue_off, jint jvalue_len) {
auto* it = reinterpret_cast<ROCKSDB_NAMESPACE::Iterator*>(handle);
ROCKSDB_NAMESPACE::Slice value_slice = it->value();
jsize copy_size = std::min(static_cast<uint32_t>(value_slice.size()),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

java/rocksjni/iterator.cc Outdated Show resolved Hide resolved
public int value(ByteBuffer value) {
assert (isOwningHandle() && value.isDirect());
int result = valueDirect0(nativeHandle_, value, value.position(), value.remaining());
public int value(final ByteBuffer value) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we plan to support more methods in the future? RocksDB.get/put/delete and WriteBatch.put/delete

Copy link
Collaborator

@adamretter adamretter Dec 7, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@javeme Yes, but that will be done in separate PRs

@adamretter
Copy link
Collaborator

@jay-zhuang @mrambacher Can we get some review/merge here please?

auto* it = reinterpret_cast<ROCKSDB_NAMESPACE::Iterator*>(handle);
it->Seek(target_slice);
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we do something either through templates or otherwise to reduce the code duplication here? Essentially the same code is in multiple places.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've done some helper-based stuff.

void Java_org_rocksdb_RocksIterator_seekByteArray0(
JNIEnv* env, jobject /*jobj*/, jlong handle, jbyteArray jtarget,
jint jtarget_off, jint jtarget_len) {
const std::unique_ptr<char[]> target(new char[jtarget_len]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to understand if this is correct. Memory is being allocated here and freed at the end of this method. But it is also being passed to GetByteArrayRegion. Some comments here would help those (like me) who are less familiar with the JNIEnv understand what is going on.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GetByteArrayRegion is a copy from the Java object into a C++ buffer (in this case the char[] contents). These are being used as the slice key to the seek. I know you need to look up what GetByteArrayRegion does to grok this, but I think an accompanying comment would turn into an overly verbose half-wrong explanation of GetByteArrayRegion and I think the right thing is to let the code speak for itself, at the cost of a bit of reading time. I'm willing to be argued out of this position.

@alanpaxton alanpaxton force-pushed the fb-6282-java-iterator-bb-extension branch from e90a6a3 to 48ab703 Compare January 17, 2022 10:19
@alanpaxton alanpaxton force-pushed the fb-6282-java-iterator-bb-extension branch from a9cc7ae to c59f2eb Compare February 14, 2022 11:53
@alanpaxton
Copy link
Contributor Author

I've gone through and done what I hope answers your concerns @Javame @mrambacher . I think it would be good for this to get into Rocks 7 if you can give it the once over.

@adamretter
Copy link
Collaborator

@jay-zhuang Can we get this merged for Rocks 7 please?

Copy link
Collaborator

@adamretter adamretter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks @alanpaxton

Alan Paxton and others added 15 commits March 24, 2022 10:09
Rework tests to be TDD for key(), value()
Implement JNI for key() for indirect

Left to do - tests for seek(), implement value(), and seek()
And associated test now passes.
SstFileReaderIterator and WBWIRocksIterator stubbed.
Tests for WBWI.
A bit of improvement to the WBWI tests.
Same pattern of implementing a native byte[] method with offsets.
seek0()/seekForPrev0(), methods using GetByteArrayElements now share a helper with seekByteArray0()/seekByteArrayForPrev0().
@alanpaxton alanpaxton force-pushed the fb-6282-java-iterator-bb-extension branch from 6e19562 to 58234c5 Compare March 24, 2022 10:09
@darrenclark
Copy link

Thanks for making this change, really looking forward to this!

I ran some quick benchmarks using indirect ByteBuffers in our iterator-heavy app and it was a significant performance boost.

@facebook-github-bot
Copy link
Contributor

@jay-zhuang has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Java: Add methods to pass byte array to key/value in iterator
6 participants