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

Fix performance bug in Java API get() functions when key is NotFound #13049

Open
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

alanpaxton
Copy link
Contributor

When a key did not exist in the system, various get() calls from the Java API were using an exception-based return path within the C++ stubs used by the Java/JNI API, because we considered that a non-existent key was a problem. But it's a common pattern and throwing an exception was reducing the overall performance of NotFound get()s by about 3x in the cached case we measured.

We have removed NotFound from the error path; exceptions are still used to handle other exceptional cases, but we explicitly handle ok() and IsNotFound() status from the underlying get() calls without using exceptions. This also
applies to various transaction versions of get().

Finally we noted (provoked in our testing) a couple of cases where some variants of calls to get() a key were not tested for non-existent keys, and we added tests.

Closes #13023

@alanpaxton alanpaxton marked this pull request as draft October 2, 2024 13:58
trazfr added a commit to trazfr/rocksdbjni-miss-perfs that referenced this pull request Oct 3, 2024
@alanpaxton alanpaxton force-pushed the eb/expensive-jni-misses-13023-jmh-fix branch from 3519c07 to e028be5 Compare November 4, 2024 16:30
@rhubner
Copy link
Contributor

rhubner commented Nov 5, 2024

Hello @alanpaxton,

looks good for me. Only one question, can merge operation exit with status not found? The reason why I'm asking is because we changes signature of method ThrowOnError and not it return status and doesn't throw exception when status is not_found.
I'm talking about these methods :

  • Java_org_rocksdb_RocksDB_merge__J_3BII_3BIIJ
  • Java_org_rocksdb_RocksDB_merge__JJ_3BII_3BII
  • Java_org_rocksdb_RocksDB_merge__JJ_3BII_3BIIJ
  • Java_org_rocksdb_Transaction_merge__J_3BII_3BIIJZ
  • Java_org_rocksdb_Transaction_merge__J_3BII_3BII
  • Java_org_rocksdb_Transaction_mergeDirect__JLjava_nio_ByteBuffer_2IILjava_nio_ByteBuffer_2IIJZ
  • Java_org_rocksdb_Transaction_mergeDirect__JLjava_nio_ByteBuffer_2IILjava_nio_ByteBuffer_2II
  • Java_org_rocksdb_Transaction_mergeUntracked
  • Java_org_rocksdb_Transaction_mergeUntrackedDirect

@alanpaxton
Copy link
Contributor Author

Hello @alanpaxton,

looks good for me. Only one question, can merge operation exit with status not found? The reason why I'm asking is because we changes signature of method ThrowOnError and not it return status and doesn't throw exception when status is not_found. I'm talking about these methods :

  • Java_org_rocksdb_RocksDB_merge__J_3BII_3BIIJ
  • Java_org_rocksdb_RocksDB_merge__JJ_3BII_3BII
  • Java_org_rocksdb_RocksDB_merge__JJ_3BII_3BIIJ
  • Java_org_rocksdb_Transaction_merge__J_3BII_3BIIJZ
  • Java_org_rocksdb_Transaction_merge__J_3BII_3BII
  • Java_org_rocksdb_Transaction_mergeDirect__JLjava_nio_ByteBuffer_2IILjava_nio_ByteBuffer_2IIJZ
  • Java_org_rocksdb_Transaction_mergeDirect__JLjava_nio_ByteBuffer_2IILjava_nio_ByteBuffer_2II
  • Java_org_rocksdb_Transaction_mergeUntracked
  • Java_org_rocksdb_Transaction_mergeUntrackedDirect

@rhubner No, I can't see how NotFound can come back from a merge. It's always a valid operation to merge with no previously written value, if I understand the semantics correctly.

@alanpaxton alanpaxton force-pushed the eb/expensive-jni-misses-13023-jmh-fix branch from e028be5 to 479acd0 Compare November 5, 2024 16:09
@alanpaxton alanpaxton marked this pull request as ready for review November 5, 2024 16:09
Performance of NotFound case has been bad - see facebook#13023
Some jmh tests to measure this, prior to fixing it.
Handling NotFound should not go through the (horribly slow) C++ exception mechanism, because it is the expected/standard path in many cases.

Change KVException::ThrowOnError to return a status when ok() or NotFound(), and the caller has to handle that status. Retain the exception mechanism for exceptions, it does simplifiy the flow and reduce checking.
get / getDirect / getForUpdate

Repair performance by avoiding the C++ exception path on NotFound.
Previous commit on this change altered behaviour of ROCKSDB_NAMESPACE::KVException::ThrowOnError to not throw on NotFound,
this change is also necessary to reinstate correct behaviour.
Add extra tests for getDirect() —> NotFound where a potential gap existed
Add a couple of extra tests around NotFound for comfort
@alanpaxton alanpaxton force-pushed the eb/expensive-jni-misses-13023-jmh-fix branch from 479acd0 to b2b87da Compare November 11, 2024 10:39
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: the misses in rocksdbjni are very expensive
3 participants