mirror of
https://github.com/facebook/rocksdb.git
synced 2026-10-23 08:09:02 +03:00
Summary: ## Summary Pull Request resolved: https://github.com/facebook/rocksdb/pull/15073 The callback-based async read APIs make coroutine-native implementations and StackableDB composition awkward because wrappers must bridge callbacks back into tasks. This change introduces `CoroDB` as a side capability exposing lazy `GetCoroutine` and `MultiGetCoroutine` tasks. `DBImpl` and `CompactedDBImpl` implement this capability directly, while `DB::GetAsync` and `DB::MultiGetAsync` remain available as compatibility entry points with synchronous fallback. The native interface should also be more efficient because callers directly await the DB coroutine. It avoids the callback/Baton adapter, callback context handoff, and explicit rescheduling required for each request. Native tasks must run on the DB filesystem read executor's EventBase; debug builds verify this affinity. Public API documentation, a release note, and native-coroutine support in `db_bench` and `db_stress` are included. ## Dispatch DB::GetAsync -> GetCoroDB() on the concrete DB -> virtual CoroDB::GetCoroutine(...) -> DBImpl::GetCoroutine or CompactedDBImpl::GetCoroutine -> AsyncCallback::OnComplete(...) Virtual dispatch selects the coroutine implementation belonging to the concrete DB while preserving the existing callback API. ## Statistics Coroutine reads preserve RocksDB's TLS statistics behavior while keeping concurrent requests isolated. Each top-level task copies only the caller's statistics configuration—`PerfLevel`, per-level perf context enablement, and IO statistics enablement—into fresh request-local `PerfContext` and `IOStatsContext` objects. Existing counters are not inherited. If both perf and IO statistics are disabled, no request statistics context is installed. Folly `RequestContext` preserves these contexts across suspension and resumption on the read executor's EventBase. At completion, RocksDB publishes the request's collected values to TLS, allowing the awaiting caller to use `get_perf_context()` and `get_iostats_context()` as after a synchronous read. Callers must consume or copy them before leaving that EventBase. Statistics scopes are installed only by top-level coroutine reads and cannot be nested. ## Benchmarks Compared the previous `GetAsync` callback bridge with native `GetCoroutine`. Both variants used optimized builds, the same compacted DB, a fixed seed, eight executor threads, ten jobs per thread, and 2.56M reads per invocation. Results are the mean of three independent invocations using the default RocksDB block cache. A sequential read warmed the OS page cache before the non-direct-read measurements. | Workload | `GetAsync` bridge | Native `GetCoroutine` | Change | | Direct I/O | 237,710 ops/s | 243,588 ops/s | +2.47% | | Warm OS page cache | 783,859 ops/s | 891,531 ops/s | +13.74% | The direct-I/O difference is within observed run-to-run variation. When reads are served from the OS page cache and API overhead is a larger portion of latency, the native interface improves throughput by 13.74%. Every invocation completed all requested reads. ```bash db_bench \ --benchmarks=readrandomcoroutine \ --db=$CORO_BENCH_DB \ --use_existing_db=true \ --num=2000000 \ --value_size=1024 \ --compression_type=none \ --threads=8 \ --coro_jobs_per_thread=10 \ --reads=320000 \ --use_direct_reads=<true|false> \ --perf_level=1 \ --statistics=true \ --seed=20260807 ``` Reviewed By: xingbowang Differential Revision: D115232511 fbshipit-source-id: 30b48da2a798094d9080178f5430aae26e6c5954