diff --git a/include/rocksdb/cache.h b/include/rocksdb/cache.h index 360d09656..4e4b0e19c 100644 --- a/include/rocksdb/cache.h +++ b/include/rocksdb/cache.h @@ -104,6 +104,9 @@ class Cache { // returns the memory size for the entries residing in the cache. virtual size_t GetUsage() const = 0; + // returns the memory size for a specific entry in the cache. + virtual size_t GetUsage(Handle* handle) const = 0; + // returns the memory size for the entries in use by the system virtual size_t GetPinnedUsage() const = 0; diff --git a/include/rocksdb/statistics.h b/include/rocksdb/statistics.h index 10982fe3d..9a21fe174 100644 --- a/include/rocksdb/statistics.h +++ b/include/rocksdb/statistics.h @@ -45,6 +45,10 @@ enum Tickers : uint32_t { BLOCK_CACHE_DATA_MISS, // # of times cache hit when accessing data block from block cache. BLOCK_CACHE_DATA_HIT, + // # of bytes read from cache. + BLOCK_CACHE_BYTES_READ, + // # of bytes written into cache. + BLOCK_CACHE_BYTES_WRITE, // # of times bloom filter has avoided file reads. BLOOM_FILTER_USEFUL, @@ -177,6 +181,8 @@ const std::vector> TickersNameMap = { {BLOCK_CACHE_FILTER_HIT, "rocksdb.block.cache.filter.hit"}, {BLOCK_CACHE_DATA_MISS, "rocksdb.block.cache.data.miss"}, {BLOCK_CACHE_DATA_HIT, "rocksdb.block.cache.data.hit"}, + {BLOCK_CACHE_BYTES_READ, "rocksdb.block.cache.bytes.read"}, + {BLOCK_CACHE_BYTES_WRITE, "rocksdb.block.cache.bytes.write"}, {BLOOM_FILTER_USEFUL, "rocksdb.bloom.filter.useful"}, {MEMTABLE_HIT, "rocksdb.memtable.hit"}, {MEMTABLE_MISS, "rocksdb.memtable.miss"}, diff --git a/table/block_based_table_reader.cc b/table/block_based_table_reader.cc index 6ffb8280a..b11327248 100644 --- a/table/block_based_table_reader.cc +++ b/table/block_based_table_reader.cc @@ -117,6 +117,9 @@ Cache::Handle* GetEntryFromCache(Cache* block_cache, const Slice& key, PERF_COUNTER_ADD(block_cache_hit_count, 1); // overall cache hit RecordTick(statistics, BLOCK_CACHE_HIT); + // total bytes read from cache + RecordTick(statistics, BLOCK_CACHE_BYTES_READ, + block_cache->GetUsage(cache_handle)); // block-type specific cache hit RecordTick(statistics, block_cache_hit_ticker); } else { @@ -795,6 +798,8 @@ Status BlockBasedTable::PutDataBlockToCache( block->value->usable_size(), &DeleteCachedEntry); RecordTick(statistics, BLOCK_CACHE_ADD); + RecordTick(statistics, BLOCK_CACHE_BYTES_WRITE, + block->value->usable_size()); assert(reinterpret_cast(block_cache->Value(block->cache_handle)) == block->value); } @@ -886,6 +891,7 @@ BlockBasedTable::CachableEntry BlockBasedTable::GetFilter( cache_handle = block_cache->Insert(key, filter, filter_size, &DeleteCachedEntry); RecordTick(statistics, BLOCK_CACHE_ADD); + RecordTick(statistics, BLOCK_CACHE_BYTES_WRITE, filter_size); } } @@ -944,6 +950,8 @@ Iterator* BlockBasedTable::NewIndexIterator(const ReadOptions& read_options, block_cache->Insert(key, index_reader, index_reader->usable_size(), &DeleteCachedEntry); RecordTick(statistics, BLOCK_CACHE_ADD); + RecordTick(statistics, BLOCK_CACHE_BYTES_WRITE, + index_reader->usable_size()); } assert(cache_handle); diff --git a/table/table_test.cc b/table/table_test.cc index 3c64b0e78..e21503b8f 100644 --- a/table/table_test.cc +++ b/table/table_test.cc @@ -1423,6 +1423,9 @@ class BlockCachePropertiesSnapshot { filter_block_cache_miss = statistics->getTickerCount(BLOCK_CACHE_FILTER_MISS); filter_block_cache_hit = statistics->getTickerCount(BLOCK_CACHE_FILTER_HIT); + block_cache_bytes_read = statistics->getTickerCount(BLOCK_CACHE_BYTES_READ); + block_cache_bytes_write = + statistics->getTickerCount(BLOCK_CACHE_BYTES_WRITE); } void AssertIndexBlockStat(int64_t expected_index_block_cache_miss, @@ -1453,6 +1456,10 @@ class BlockCachePropertiesSnapshot { block_cache_hit); } + int64_t GetCacheBytesRead() { return block_cache_bytes_read; } + + int64_t GetCacheBytesWrite() { return block_cache_bytes_write; } + private: int64_t block_cache_miss = 0; int64_t block_cache_hit = 0; @@ -1462,6 +1469,8 @@ class BlockCachePropertiesSnapshot { int64_t data_block_cache_hit = 0; int64_t filter_block_cache_miss = 0; int64_t filter_block_cache_hit = 0; + int64_t block_cache_bytes_read = 0; + int64_t block_cache_bytes_write = 0; }; // Make sure, by default, index/filter blocks were pre-loaded (meaning we won't @@ -1537,12 +1546,17 @@ TEST_F(BlockBasedTableTest, FilterBlockInBlockCache) { // Since block_cache is disabled, no cache activities will be involved. unique_ptr iter; + int64_t last_cache_bytes_read = 0; // At first, no block will be accessed. { BlockCachePropertiesSnapshot props(options.statistics.get()); // index will be added to block cache. props.AssertEqual(1, // index block miss 0, 0, 0); + ASSERT_EQ(props.GetCacheBytesRead(), 0); + ASSERT_EQ(props.GetCacheBytesWrite(), + table_options.block_cache->GetUsage()); + last_cache_bytes_read = props.GetCacheBytesRead(); } // Only index block will be accessed @@ -1554,6 +1568,11 @@ TEST_F(BlockBasedTableTest, FilterBlockInBlockCache) { // value; other numbers remain the same. props.AssertEqual(1, 0 + 1, // index block hit 0, 0); + // Cache hit, bytes read from cache should increase + ASSERT_GT(props.GetCacheBytesRead(), last_cache_bytes_read); + ASSERT_EQ(props.GetCacheBytesWrite(), + table_options.block_cache->GetUsage()); + last_cache_bytes_read = props.GetCacheBytesRead(); } // Only data block will be accessed @@ -1562,6 +1581,11 @@ TEST_F(BlockBasedTableTest, FilterBlockInBlockCache) { BlockCachePropertiesSnapshot props(options.statistics.get()); props.AssertEqual(1, 1, 0 + 1, // data block miss 0); + // Cache miss, Bytes read from cache should not change + ASSERT_EQ(props.GetCacheBytesRead(), last_cache_bytes_read); + ASSERT_EQ(props.GetCacheBytesWrite(), + table_options.block_cache->GetUsage()); + last_cache_bytes_read = props.GetCacheBytesRead(); } // Data block will be in cache @@ -1571,6 +1595,11 @@ TEST_F(BlockBasedTableTest, FilterBlockInBlockCache) { BlockCachePropertiesSnapshot props(options.statistics.get()); props.AssertEqual(1, 1 + 1, /* index block hit */ 1, 0 + 1 /* data block hit */); + // Cache hit, bytes read from cache should increase + ASSERT_GT(props.GetCacheBytesRead(), last_cache_bytes_read); + ASSERT_EQ(props.GetCacheBytesWrite(), + table_options.block_cache->GetUsage()); + last_cache_bytes_read = props.GetCacheBytesRead(); } // release the iterator so that the block cache can reset correctly. iter.reset(); @@ -1587,6 +1616,8 @@ TEST_F(BlockBasedTableTest, FilterBlockInBlockCache) { BlockCachePropertiesSnapshot props(options.statistics.get()); props.AssertEqual(1, // index block miss 0, 0, 0); + // Cache miss, Bytes read from cache should not change + ASSERT_EQ(props.GetCacheBytesRead(), 0); } { @@ -1598,6 +1629,8 @@ TEST_F(BlockBasedTableTest, FilterBlockInBlockCache) { props.AssertEqual(1 + 1, // index block miss 0, 0, // data block miss 0); + // Cache hit, bytes read from cache should increase + ASSERT_EQ(props.GetCacheBytesRead(), 0); } { @@ -1607,6 +1640,8 @@ TEST_F(BlockBasedTableTest, FilterBlockInBlockCache) { BlockCachePropertiesSnapshot props(options.statistics.get()); props.AssertEqual(2, 0, 0 + 1, // data block miss 0); + // Cache miss, Bytes read from cache should not change + ASSERT_EQ(props.GetCacheBytesRead(), 0); } iter.reset(); diff --git a/util/cache.cc b/util/cache.cc index dcdd27a83..e64c01e7b 100644 --- a/util/cache.cc +++ b/util/cache.cc @@ -540,6 +540,11 @@ class ShardedLRUCache : public Cache { } return usage; } + + virtual size_t GetUsage(Handle* handle) const override { + return reinterpret_cast(handle)->charge; + } + virtual size_t GetPinnedUsage() const override { // We will not lock the cache when getting the usage from shards. int num_shards = 1 << num_shard_bits_;