mirror of
https://github.com/facebook/rocksdb.git
synced 2026-10-24 19:59:35 +03:00
Summary: `BlockBasedTableIterator::SeekImpl()` sets `seek_key_prefix_for_readahead_trimming_` only when given a seek key, and `ResetBlockCacheLookupVar()` does not clear it. After a `Seek()`, a `SeekToFirst()` on the same iterator trims readahead against the previous seek key's prefix. `DBIter::SeekToFirst()` under `prefix_same_as_start` takes its prefix from the first key found, so the old prefix does not describe the keys being scanned. With the stale prefix, `IsNextBlockOutOfReadaheadBound()` is true at every block instead of only at the prefix boundary, and each prefetch is clamped to the current block. The same predicate sets `is_index_out_of_bound_`, which `FindBlockForward()` converts to `is_out_of_bound_` and ends the scan. Under `ReadOptions::async_io` this drops keys. The bug needs `auto_readahead_size` and a preceding `Seek()` that reads no data block. A `Seek()` that lands on a key leaves the prefetch buffer anchored above the scan, and the trimming callback is not called. The bug does not occur under `allow_mmap_reads`, where `FilePrefetchBuffer` is constructed disabled. The fix clears the prefix in `SeekToFirst()`, so prefix-based trimming is disabled for that positioning. The `auto_readahead_size` documentation in `include/rocksdb/options.h` already says prefix-based trimming requires `Seek(key)`. On buffered reads with `prefix_same_as_start`, `auto_readahead_size` and `readahead_size=8192`, a cold-cache `SeekToFirst()` scan of 2M keys in a single 222 MB file, preceded on the same iterator by a `Seek()` past the last key, took 391 ms before and 308 ms after. The same scan with no preceding `Seek()` takes 307 ms. Under direct IO on a local disk it went from 33.1 s to 11.8 s. Data blocks read are unchanged; file reads drop by 3x. Also fixes a pre-existing test bug: `SeekParallelizationTestWithPosix` asserts on `number_async_seek` without resetting that cumulative thread-local, unlike its three siblings. The new tests move `prefetch_test` from 11 shards to 13, so different tests share a process, and the assertion fails at the parent commit under that grouping. Pull Request resolved: https://github.com/facebook/rocksdb/pull/15216 Test Plan: New regression test in `PrefetchTrimReadaheadTestParam`, in sync and `async_io` variants over the fixture's three `index_shortening` modes. It runs two scans of the same keys from an equally cold block cache, differing only in a preceding `Seek()`. Reverting the `clear()` fails 3 of 6 sync parameterizations on `READAHEAD_TRIMMED` (6 vs 40) and 3 of 6 `async_io` parameterizations on key count (40 vs 1). `make check` and `ASSERT_STATUS_CHECKED=1 make check` show no new failures. `prefetch_test` 122/122, `db_iterator_test` 249/249, `table_test` 7629/7629, `block_based_table_reader_test` 5347/5347, `db_basic_test` 300/300. New cases ran 1200 times under `COERCE_CONTEXT_SWITCH=1` without failure. Added db_stress coverage for `SeekToFirst()` after `Seek()` under `prefix_same_as_start`. With the fix reverted and io_uring available, the configuration in the second commit fails 8 of 8 seeds with "Iterator diverged from control iterator"; with the fix, the same seeds pass. Reviewed By: rban1 Differential Revision: D120228466 Pulled By: xingbowang fbshipit-source-id: a4935f03a0080cc8dd4c7a8c1438404e9b8f5c3a