Summary: Add per-file sampling of "collapsible" entry reads (single deletions, merges, and kNotFound results) that may later be used to help inform read-triggered compactions. This is a better metric than `num_reads_sampled` as it is more targeted towards reads that could be avoided via compaction. The existing behavior of `num_reads_sampled` is that reads only gets sampled on iterator creation for a file. It is problematic because next/prev() calls are not sampled, nor are additional seeks(). This PR moves sampling to per-seek/next granularity within `LevelIterator` and adds a new `num_collapsible_entry_reads_sampled` counter that tracks how often a file serves entries that could be eliminated by compaction. Note only L1+ files have iterator seeks/nexts/prevs sampled. Introducing this at L0 would require wrapping table reader iterators, introducing a performance cost. ## Key changes - **New counter `num_collapsible_entry_reads_sampled`** in `FileSampledStats` tracks sampled reads that encounter deletions, single deletions, merges, or kNotFound results in both Get and Iterator paths. - **Moved sampling from file-open to per-operation** in `LevelIterator`: sampling now happens in `SampleRead()` called from `Seek()`, `SeekForPrev()`, `SeekToFirst()`, `SeekToLast()`, `Next()`, `NextAndGetResult()`, and `Prev()`. The `should_sample` parameter was removed from `LevelIterator`'s constructor. - **Differentiated sampling rate for Next() vs Seek()**: `should_sample_file_read_next()` uses a 64x lower sampling rate (`kFileReadSampleRate * 64`) since Next() is cheaper than Seek() and called more frequently. - **Collapsible tracking in Get path**: `Version::Get()` now increments the collapsible counter when `GetContext::State()` is `kNotFound`, `kMerge`, or `kDeleted`. - **Collapsible tracking in MultiGet path**: `MultiGetFromSST` also increments the collapsible counter for the same states. Pull Request resolved: https://github.com/facebook/rocksdb/pull/14434 Test Plan: - Added new DB tests for both num_reads_sampled and num_collapsible_entry_reads_sampled ### Benchmark results (readrandom, readseq) Setup: 1M keys, 16-byte keys, 100-byte values, no compression, fillrandom+compact | Benchmark | Params | ops/s (main) | ops/s (feature) | % change | |------------|--------------------|-------------|--------------------------|----------| | readrandom | seed=1, threads=1 | 387,194 | 389,449 | +0.6% | | readseq | seed=1, threads=1 | 5,598,371 | 5,572,975 | -0.5% | No meaningful performance regression observed — differences are within run-to-run noise. Reviewed By: xingbowang Differential Revision: D95613793 Pulled By: joshkang97 fbshipit-source-id: 9dd09c9b7527b148424bde5686f4157c7a9e1214
40 lines
1.5 KiB
C++
40 lines
1.5 KiB
C++
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
|
|
// This source code is licensed under both the GPLv2 (found in the
|
|
// COPYING file in the root directory) and Apache 2.0 License
|
|
// (found in the LICENSE.Apache file in the root directory).
|
|
//
|
|
#pragma once
|
|
#include "db/version_edit.h"
|
|
#include "test_util/sync_point.h"
|
|
#include "util/random.h"
|
|
|
|
namespace ROCKSDB_NAMESPACE {
|
|
static const uint32_t kFileReadSampleRate = 1024;
|
|
static const uint32_t kFileReadNextSampleRate =
|
|
kFileReadSampleRate * 64; // Must be kept a power of 2
|
|
|
|
inline bool should_sample_file_read() {
|
|
bool result = (Random::GetTLSInstance()->Next() % kFileReadSampleRate == 307);
|
|
TEST_SYNC_POINT_CALLBACK("should_sample_file_read:override", &result);
|
|
return result;
|
|
}
|
|
|
|
inline bool should_sample_file_read_next() {
|
|
// Decrease probability of sampling next() to discount it as it is cheaper
|
|
// than seek()
|
|
thread_local uint32_t counter = 0;
|
|
bool result = (++counter & (kFileReadNextSampleRate - 1)) == 0;
|
|
TEST_SYNC_POINT_CALLBACK("should_sample_file_read:override", &result);
|
|
return result;
|
|
}
|
|
|
|
inline void sample_file_read_inc(const FileMetaData* meta) {
|
|
meta->stats.num_reads_sampled.fetch_add(kFileReadSampleRate,
|
|
std::memory_order_relaxed);
|
|
}
|
|
|
|
inline void sample_collapsible_entry_file_read_inc(const FileMetaData* meta) {
|
|
meta->stats.num_collapsible_entry_reads_sampled.fetch_add(
|
|
kFileReadSampleRate, std::memory_order_relaxed);
|
|
}
|
|
} // namespace ROCKSDB_NAMESPACE
|