Add a stat to count secondary cache hits (#8666)

Summary:
Add a stat for secondary cache hits. The ```Cache::Lookup``` API had an unused ```stats``` parameter. This PR uses that to pass the pointer to a ```Statistics``` object that ```LRUCache``` uses to record the stat.

Pull Request resolved: https://github.com/facebook/rocksdb/pull/8666

Test Plan: Update a unit test in lru_cache_test

Reviewed By: zhichao-cao

Differential Revision: D30353816

Pulled By: anand1976

fbshipit-source-id: 2046f78b460428877a26ffdd2bb914ae47dfbe77
This commit is contained in:
anand76 2021-08-16 21:00:17 -07:00 committed by Facebook GitHub Bot
parent a207c27809
commit add68bd28a
11 changed files with 41 additions and 13 deletions

View File

@ -17,6 +17,7 @@
* Add a comment to suggest btrfs user to disable file preallocation by setting `options.allow_fallocate=false`. * Add a comment to suggest btrfs user to disable file preallocation by setting `options.allow_fallocate=false`.
* Fast forward option in Trace replay changed to double type to allow replaying at a lower speed, by settings the value between 0 and 1. This option can be set via `ReplayOptions` in `Replayer::Replay()`, or via `--trace_replay_fast_forward` in db_bench. * Fast forward option in Trace replay changed to double type to allow replaying at a lower speed, by settings the value between 0 and 1. This option can be set via `ReplayOptions` in `Replayer::Replay()`, or via `--trace_replay_fast_forward` in db_bench.
* Add property `LiveSstFilesSizeAtTemperature` to retrieve sst file size at different temperature. * Add property `LiveSstFilesSizeAtTemperature` to retrieve sst file size at different temperature.
* Added a stat rocksdb.secondary.cache.hits
## Public API change ## Public API change
* Added APIs to decode and replay trace file via Replayer class. Added `DB::NewDefaultReplayer()` to create a default Replayer instance. Added `TraceReader::Reset()` to restart reading a trace file. Created trace_record.h and utilities/replayer.h files to access decoded Trace records and replay them. * Added APIs to decode and replay trace file via Replayer class. Added `DB::NewDefaultReplayer()` to create a default Replayer instance. Added `TraceReader::Reset()` to restart reading a trace file. Created trace_record.h and utilities/replayer.h files to access decoded Trace records and replay them.

View File

@ -280,7 +280,8 @@ class ClockCacheShard final : public CacheShard {
Cache::Handle* Lookup(const Slice& key, uint32_t hash, Cache::Handle* Lookup(const Slice& key, uint32_t hash,
const Cache::CacheItemHelper* /*helper*/, const Cache::CacheItemHelper* /*helper*/,
const Cache::CreateCallback& /*create_cb*/, const Cache::CreateCallback& /*create_cb*/,
Cache::Priority /*priority*/, bool /*wait*/) override { Cache::Priority /*priority*/, bool /*wait*/,
Statistics* /*stats*/) override {
return Lookup(key, hash); return Lookup(key, hash);
} }
bool Release(Cache::Handle* handle, bool /*useful*/, bool Release(Cache::Handle* handle, bool /*useful*/,

8
cache/lru_cache.cc vendored
View File

@ -13,6 +13,7 @@
#include <cstdint> #include <cstdint>
#include <cstdio> #include <cstdio>
#include "monitoring/statistics.h"
#include "util/mutexlock.h" #include "util/mutexlock.h"
namespace ROCKSDB_NAMESPACE { namespace ROCKSDB_NAMESPACE {
@ -418,7 +419,7 @@ Cache::Handle* LRUCacheShard::Lookup(
const Slice& key, uint32_t hash, const Slice& key, uint32_t hash,
const ShardedCache::CacheItemHelper* helper, const ShardedCache::CacheItemHelper* helper,
const ShardedCache::CreateCallback& create_cb, Cache::Priority priority, const ShardedCache::CreateCallback& create_cb, Cache::Priority priority,
bool wait) { bool wait, Statistics* stats) {
LRUHandle* e = nullptr; LRUHandle* e = nullptr;
{ {
MutexLock l(&mutex_); MutexLock l(&mutex_);
@ -471,11 +472,16 @@ Cache::Handle* LRUCacheShard::Lookup(
e->Unref(); e->Unref();
e->Free(); e->Free();
e = nullptr; e = nullptr;
} else {
RecordTick(stats, SECONDARY_CACHE_HITS);
} }
} else { } else {
// If wait is false, we always return a handle and let the caller // If wait is false, we always return a handle and let the caller
// release the handle after checking for success or failure // release the handle after checking for success or failure
e->SetIncomplete(true); e->SetIncomplete(true);
// This may be slightly inaccurate, if the lookup eventually fails.
// But the probability is very low.
RecordTick(stats, SECONDARY_CACHE_HITS);
} }
} }
} }

7
cache/lru_cache.h vendored
View File

@ -319,10 +319,11 @@ class ALIGN_AS(CACHE_LINE_SIZE) LRUCacheShard final : public CacheShard {
virtual Cache::Handle* Lookup(const Slice& key, uint32_t hash, virtual Cache::Handle* Lookup(const Slice& key, uint32_t hash,
const ShardedCache::CacheItemHelper* helper, const ShardedCache::CacheItemHelper* helper,
const ShardedCache::CreateCallback& create_cb, const ShardedCache::CreateCallback& create_cb,
ShardedCache::Priority priority, ShardedCache::Priority priority, bool wait,
bool wait) override; Statistics* stats) override;
virtual Cache::Handle* Lookup(const Slice& key, uint32_t hash) override { virtual Cache::Handle* Lookup(const Slice& key, uint32_t hash) override {
return Lookup(key, hash, nullptr, nullptr, Cache::Priority::LOW, true); return Lookup(key, hash, nullptr, nullptr, Cache::Priority::LOW, true,
nullptr);
} }
virtual bool Release(Cache::Handle* handle, bool /*useful*/, virtual bool Release(Cache::Handle* handle, bool /*useful*/,
bool force_erase) override { bool force_erase) override {

View File

@ -468,6 +468,7 @@ TEST_F(LRUSecondaryCacheTest, BasicTest) {
std::make_shared<TestSecondaryCache>(2048); std::make_shared<TestSecondaryCache>(2048);
opts.secondary_cache = secondary_cache; opts.secondary_cache = secondary_cache;
std::shared_ptr<Cache> cache = NewLRUCache(opts); std::shared_ptr<Cache> cache = NewLRUCache(opts);
std::shared_ptr<Statistics> stats = CreateDBStatistics();
Random rnd(301); Random rnd(301);
std::string str1 = rnd.RandomString(1020); std::string str1 = rnd.RandomString(1020);
@ -476,22 +477,26 @@ TEST_F(LRUSecondaryCacheTest, BasicTest) {
str1.length())); str1.length()));
std::string str2 = rnd.RandomString(1020); std::string str2 = rnd.RandomString(1020);
TestItem* item2 = new TestItem(str2.data(), str2.length()); TestItem* item2 = new TestItem(str2.data(), str2.length());
// k2 should be demoted to NVM // k1 should be demoted to NVM
ASSERT_OK(cache->Insert("k2", item2, &LRUSecondaryCacheTest::helper_, ASSERT_OK(cache->Insert("k2", item2, &LRUSecondaryCacheTest::helper_,
str2.length())); str2.length()));
Cache::Handle* handle; Cache::Handle* handle;
handle = cache->Lookup("k2", &LRUSecondaryCacheTest::helper_, handle =
test_item_creator, Cache::Priority::LOW, true); cache->Lookup("k2", &LRUSecondaryCacheTest::helper_, test_item_creator,
Cache::Priority::LOW, true, stats.get());
ASSERT_NE(handle, nullptr); ASSERT_NE(handle, nullptr);
cache->Release(handle); cache->Release(handle);
// This lookup should promote k1 and demote k2 // This lookup should promote k1 and demote k2
handle = cache->Lookup("k1", &LRUSecondaryCacheTest::helper_, handle =
test_item_creator, Cache::Priority::LOW, true); cache->Lookup("k1", &LRUSecondaryCacheTest::helper_, test_item_creator,
Cache::Priority::LOW, true, stats.get());
ASSERT_NE(handle, nullptr); ASSERT_NE(handle, nullptr);
cache->Release(handle); cache->Release(handle);
ASSERT_EQ(secondary_cache->num_inserts(), 2u); ASSERT_EQ(secondary_cache->num_inserts(), 2u);
ASSERT_EQ(secondary_cache->num_lookups(), 1u); ASSERT_EQ(secondary_cache->num_lookups(), 1u);
ASSERT_EQ(stats->getTickerCount(SECONDARY_CACHE_HITS),
secondary_cache->num_lookups());
cache.reset(); cache.reset();
secondary_cache.reset(); secondary_cache.reset();

View File

@ -83,10 +83,10 @@ Cache::Handle* ShardedCache::Lookup(const Slice& key,
const CacheItemHelper* helper, const CacheItemHelper* helper,
const CreateCallback& create_cb, const CreateCallback& create_cb,
Priority priority, bool wait, Priority priority, bool wait,
Statistics* /*stats*/) { Statistics* stats) {
uint32_t hash = HashSlice(key); uint32_t hash = HashSlice(key);
return GetShard(Shard(hash)) return GetShard(Shard(hash))
->Lookup(key, hash, helper, create_cb, priority, wait); ->Lookup(key, hash, helper, create_cb, priority, wait, stats);
} }
bool ShardedCache::IsReady(Handle* handle) { bool ShardedCache::IsReady(Handle* handle) {

View File

@ -34,7 +34,8 @@ class CacheShard {
virtual Cache::Handle* Lookup(const Slice& key, uint32_t hash, virtual Cache::Handle* Lookup(const Slice& key, uint32_t hash,
const Cache::CacheItemHelper* helper, const Cache::CacheItemHelper* helper,
const Cache::CreateCallback& create_cb, const Cache::CreateCallback& create_cb,
Cache::Priority priority, bool wait) = 0; Cache::Priority priority, bool wait,
Statistics* stats) = 0;
virtual bool Release(Cache::Handle* handle, bool useful, virtual bool Release(Cache::Handle* handle, bool useful,
bool force_erase) = 0; bool force_erase) = 0;
virtual bool IsReady(Cache::Handle* handle) = 0; virtual bool IsReady(Cache::Handle* handle) = 0;

View File

@ -389,6 +389,9 @@ enum Tickers : uint32_t {
// Outdated bytes of data present on memtable at flush time. // Outdated bytes of data present on memtable at flush time.
MEMTABLE_GARBAGE_BYTES_AT_FLUSH, MEMTABLE_GARBAGE_BYTES_AT_FLUSH,
// Secondary cache statistics
SECONDARY_CACHE_HITS,
TICKER_ENUM_MAX TICKER_ENUM_MAX
}; };

View File

@ -5000,6 +5000,8 @@ class TickerTypeJni {
return -0x1C; return -0x1C;
case ROCKSDB_NAMESPACE::Tickers::MEMTABLE_GARBAGE_BYTES_AT_FLUSH: case ROCKSDB_NAMESPACE::Tickers::MEMTABLE_GARBAGE_BYTES_AT_FLUSH:
return -0x1D; return -0x1D;
case ROCKSDB_NAMESPACE::Tickers::SECONDARY_CACHE_HITS:
return -0x1E;
case ROCKSDB_NAMESPACE::Tickers::TICKER_ENUM_MAX: case ROCKSDB_NAMESPACE::Tickers::TICKER_ENUM_MAX:
// 0x5F for backwards compatibility on current minor version. // 0x5F for backwards compatibility on current minor version.
return 0x5F; return 0x5F;
@ -5330,6 +5332,8 @@ class TickerTypeJni {
return ROCKSDB_NAMESPACE::Tickers::MEMTABLE_PAYLOAD_BYTES_AT_FLUSH; return ROCKSDB_NAMESPACE::Tickers::MEMTABLE_PAYLOAD_BYTES_AT_FLUSH;
case -0x1D: case -0x1D:
return ROCKSDB_NAMESPACE::Tickers::MEMTABLE_GARBAGE_BYTES_AT_FLUSH; return ROCKSDB_NAMESPACE::Tickers::MEMTABLE_GARBAGE_BYTES_AT_FLUSH;
case -0x1E:
return ROCKSDB_NAMESPACE::Tickers::SECONDARY_CACHE_HITS;
case 0x5F: case 0x5F:
// 0x5F for backwards compatibility on current minor version. // 0x5F for backwards compatibility on current minor version.
return ROCKSDB_NAMESPACE::Tickers::TICKER_ENUM_MAX; return ROCKSDB_NAMESPACE::Tickers::TICKER_ENUM_MAX;

View File

@ -764,6 +764,11 @@ public enum TickerType {
*/ */
MEMTABLE_GARBAGE_BYTES_AT_FLUSH((byte) -0x1D), MEMTABLE_GARBAGE_BYTES_AT_FLUSH((byte) -0x1D),
/**
* Number of secondary cache hits
*/
SECONDARY_CACHE_HITS((byte) -0x1E),
TICKER_ENUM_MAX((byte) 0x5F); TICKER_ENUM_MAX((byte) 0x5F);
private final byte value; private final byte value;

View File

@ -205,6 +205,7 @@ const std::vector<std::pair<Tickers, std::string>> TickersNameMap = {
"rocksdb.memtable.payload.bytes.at.flush"}, "rocksdb.memtable.payload.bytes.at.flush"},
{MEMTABLE_GARBAGE_BYTES_AT_FLUSH, {MEMTABLE_GARBAGE_BYTES_AT_FLUSH,
"rocksdb.memtable.garbage.bytes.at.flush"}, "rocksdb.memtable.garbage.bytes.at.flush"},
{SECONDARY_CACHE_HITS, "rocksdb.secondary.cache.hits"},
}; };
const std::vector<std::pair<Histograms, std::string>> HistogramsNameMap = { const std::vector<std::pair<Histograms, std::string>> HistogramsNameMap = {