HDDS-16250. Improve RocksDB read performance by reducing unnecessary iterator positioning - #11084
Merged
Merged
Conversation
…iterator positioning Generated-by: Codex (GPT-5.6 Sol)
Contributor
There was a problem hiding this comment.
Pull request overview
This PR optimizes RocksDB-backed table iteration in HDDS by deferring initial iterator positioning until the first iterator operation, avoiding redundant native seeks (especially costly when scanning across tombstone-heavy regions). It also introduces a fast path in RDBTable#getRangeKVs that uses a point Get for exact single-entry range requests when the contract requires the start key to exist and the request is within the given prefix.
Changes:
- Deferred iterator positioning to first use in
RDBStoreAbstractIterator, eliminating construction-time seeks while preserving existing semantics for ordinary iteration (hasNext()/next()/removeFromDB()). - Added a point-
Getoptimization for exactcount == 1range requests inRDBTable#getRangeKVswhen conditions allow, avoiding iterator creation/positioning. - Expanded and adjusted unit tests to validate seek counts/order, prefix-boundary semantics, and the new point-
Getbehavior (including aliasing expectations for returned keys).
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/db/RDBStoreAbstractIterator.java | Defers initial positioning until first iterator operation; ensures explicit seeks don’t incur an extra initial seek. |
| hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/db/RDBStoreByteArrayIterator.java | Removes construction-time seekToFirst() to align with deferred initialization semantics. |
| hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/db/RDBStoreCodecBufferIterator.java | Removes construction-time seekToFirst() to align with deferred initialization semantics. |
| hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/db/RDBTable.java | Adds point-Get fast path for eligible single-entry exact ranges; retains iterator-based behavior otherwise. |
| hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/utils/db/TestRDBStoreByteArrayIterator.java | Updates iterator tests to assert no construction seek and correct seek ordering/counts. |
| hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/utils/db/TestRDBStoreCodecBufferIterator.java | Updates CodecBuffer iterator tests for deferred initialization and exact seek argument verification. |
| hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/utils/db/TestRDBTableStore.java | Adds/adjusts prefixed range test coverage for prefix-boundary and filtered/single-entry behaviors. |
| hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/utils/db/TestRDBTable.java | Adds tests ensuring eligible getRangeKVs calls use point Get and avoid iterator creation; validates key aliasing expectations. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Keep the performance change limited to lazy iterator positioning. Generated-by: Codex (GPT-5.6 Sol)
jojochuang
marked this pull request as ready for review
August 21, 2026 22:45
Contributor
Author
|
Thanks @jojochuang @rich7420 for the reviews. |
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
What changes were proposed in this pull request?
Ozone's RocksDB-backed table iterators currently position themselves at the table or prefix start during construction. Callers that then explicitly seek to another key perform two native positioning operations:
The first operation is redundant. A RocksDB seek to the logical beginning is not merely assigning a cursor to the beginning of one file: RocksDB must merge its internal sources and find the first visible key, which can require skipping a large run of uncompacted tombstones.
This PR defers initial positioning until the first iterator operation:
seek(),seekToFirst(), andseekToLast()position the iterator directly without an earlier seek.hasNext(), directnext(), andremoveFromDB()preserve the existing behavior by initializing at the table or prefix start on first use.RDBStoreAbstractIteratorand applies consistently to the byte-array andCodecBufferiterators.The change does not modify any public API, wire format, RocksDB schema, metadata layout, or caller-visible iterator semantics.
Expected benefit
The change eliminates one native RocksDB positioning operation when a caller creates an iterator and explicitly repositions it. The absolute latency reduction equals the cost of the eliminated table-start or prefix seek.
Production paths that can benefit include:
listKeysand S3ListObjects: OM creates a key-table iterator and seeks to the requested bucket, prefix, or continuation marker. First pages can benefit when the bucket sorts after a tombstone-heavy region, while later pages can benefit when the continuation marker is beyond deleted keys in the bucket.listStatus: FSO listings use directory and file prefix iterators that may seek to a later start key. LEGACY and OBJECT_STORE listings also use a table iterator followed by a start-key seek.listOpenFiles: OM seeks an open-key-table iterator to the requested path or continuation token.ListMultipartUploads: paginated requests seek a bucket-prefix iterator to the key and upload-ID marker.A standalone synthetic benchmark used RocksDB JNI 10.10.1.1, a warm cache, one thread, disabled automatic compaction, and consecutive point tombstones before a live target. The benchmark measures RocksDB positioning, not end-to-end Ozone RPC latency.
When the continuation target was beyond the tombstone band:
When both positioning operations crossed the tombstone region, removing one of them produced approximately a 2× positioning improvement.
Actual request-level improvement depends on tombstone distribution, compaction state, cache state, result decoding, OM cache merging, storage latency, and RPC processing. Little improvement is expected for compacted tables, low tombstone counts, or callers that begin ordinary iteration without explicitly repositioning the iterator.
The standalone
RocksTombstoneBench.javareproducer can be provided as a separate patch. Its header contains the exact compilation and execution commands and documents the benchmark conditions.What is the link to the Apache JIRA
https://issues.apache.org/jira/browse/HDDS-16250
How was this patch tested?
Regression tests verify that:
hasNext()and directnext()still initialize at the table or prefix beginning.hasNext()calls do not repeat initialization.seekToLast()does not first seek to the beginning.removeFromDB()preserves its implicit-start behavior.CodecBufferiterators have identical positioning behavior.Validation results:
hdds-server-frameworksuite excludingTestDU: 596 passed and 1 skipped.TestDU.testExcludePatternfails with the same error on clean master on macOS and is unrelated to this change.A wall-clock performance assertion is intentionally excluded from the unit suite because it would depend on host timing, cache state, storage, and RocksDB compaction state. The regression tests instead verify the number and order of native positioning operations deterministically.
Generated-by: Codex (GPT-5.6 Sol)