From 391885c4e4c3ea6a1bd3e32c096874fb3a9f175b Mon Sep 17 00:00:00 2001 From: Abhishek Kona Date: Fri, 2 Nov 2012 21:02:40 -0700 Subject: [PATCH] stat's collection in leveldb Summary: Prototype stat's collection. Diff is a good estimate of what the final code will look like. A few assumptions : * Used a global static instance of the statistics object. Plan to pass it to each internal function. Static allows metrics only at app level. * In the Ticker's do not do any locking. Depend on the mutex at each function of LevelDB. If we ever remove the mutex, we should change here too. The other option is use atomic objects anyways as there won't be any contention as they will be always acquired only by one thread. * The counters are dumb, increment through lifecycle. Plan to use ods etc to get last5min stat etc. Test Plan: made changes in db_bench Ran ./db_bench --statistics=1 --num=10000 --cache_size=5000 This will print the cache hit/miss stats. Reviewers: dhruba, heyongqiang Differential Revision: https://reviews.facebook.net/D6441 --- db/db_bench.cc | 7 ++++-- db/db_statistics.h | 19 ++++++++++++--- include/leveldb/statistics.h | 45 +++++++++++++++++++++++++++++++++++- table/table.cc | 6 +++++ 4 files changed, 71 insertions(+), 6 deletions(-) diff --git a/db/db_bench.cc b/db/db_bench.cc index c33179a94..792b3255f 100644 --- a/db/db_bench.cc +++ b/db/db_bench.cc @@ -574,10 +574,13 @@ class Benchmark { void PrintStatistics() { if (FLAGS_statistics) { - fprintf(stdout, "File opened:%ld closed:%ld errors:%ld\n", + fprintf(stdout, "File opened:%ld closed:%ld errors:%ld\n" + "Block Cache Hit Count:%ld Block Cache Miss Count:%ld\n", dbstats->getNumFileOpens(), dbstats->getNumFileCloses(), - dbstats->getNumFileErrors()); + dbstats->getNumFileErrors(), + dbstats->getTickerCount(BLOCK_CACHE_HIT), + dbstats->getTickerCount(BLOCK_CACHE_MISS)); } } diff --git a/db/db_statistics.h b/db/db_statistics.h index 350d52c2a..612817e7a 100644 --- a/db/db_statistics.h +++ b/db/db_statistics.h @@ -2,16 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. See the AUTHORS file for names of contributors. +#include #include +#include + #include "leveldb/statistics.h" #include "port/port.h" #include "util/mutexlock.h" - namespace leveldb { class DBStatistics: public Statistics { public: - DBStatistics() { } + DBStatistics() : allTickers_(TICKER_ENUM_MAX) { } void incNumFileOpens() { MutexLock l(&mu_); @@ -28,8 +30,19 @@ class DBStatistics: public Statistics { numFileErrors_++; } + long getTickerCount(Tickers tickerType) { + assert(tickerType < MAX_NO_TICKERS); + return allTickers_[tickerType].getCount(); + } + + void recordTick(Tickers tickerType) { + assert(tickerType < MAX_NO_TICKERS); + allTickers_[tickerType].recordTick(); + } + private: - port::Mutex mu_; + port::Mutex mu_; + std::vector allTickers_; }; } diff --git a/include/leveldb/statistics.h b/include/leveldb/statistics.h index 3286daa32..77280d879 100644 --- a/include/leveldb/statistics.h +++ b/include/leveldb/statistics.h @@ -7,9 +7,43 @@ namespace leveldb { +/** + * Keep adding ticker's here. + * Any ticker should have a value less than TICKER_ENUM_MAX. + * Add a new ticker by assigning it the current value of TICKER_ENUM_MAX + * And incrementing TICKER_ENUM_MAX. + */ +enum Tickers { + BLOCK_CACHE_MISS = 0, + BLOCK_CACHE_HIT = 1, + TICKER_ENUM_MAX = 2, +}; + + +/** + * A dumb ticker which keeps incrementing through its life time. + * Not thread safe. Locking is currently managed by external leveldb lock + */ +class Ticker { + public: + Ticker() : count_(0) { } + + inline void recordTick() { + count_++; + } + + inline uint64_t getCount() { + return count_; + } + + private: + uint64_t count_; + +}; + // Analyze the performance of a db class Statistics { - public: + public: // Create an Statistics object with default values for all fields. Statistics() : numFileOpens_(0), numFileCloses_(0), numFileErrors_(0) {} @@ -23,12 +57,21 @@ class Statistics { virtual long getNumFileErrors() { return numFileErrors_;} virtual ~Statistics() {} + virtual long getTickerCount(Tickers tickerType) = 0; + virtual void recordTick(Tickers tickerType) = 0; + protected: long numFileOpens_; long numFileCloses_; long numFileErrors_; }; +// Ease of Use functions +inline void RecordTick(Statistics* const statistics, Tickers ticker) { + if (statistics != NULL) { + statistics->recordTick(ticker); + } +}; } // namespace leveldb #endif // STORAGE_LEVELDB_INCLUDE_STATISTICS_H_ diff --git a/table/table.cc b/table/table.cc index 59117ddcb..3f255204d 100644 --- a/table/table.cc +++ b/table/table.cc @@ -9,6 +9,7 @@ #include "leveldb/env.h" #include "leveldb/filter_policy.h" #include "leveldb/options.h" +#include "leveldb/statistics.h" #include "table/block.h" #include "table/filter_block.h" #include "table/format.h" @@ -157,6 +158,7 @@ Iterator* Table::BlockReader(void* arg, bool* didIO) { Table* table = reinterpret_cast(arg); Cache* block_cache = table->rep_->options.block_cache; + Statistics* const statistics = table->rep_->options.statistics; Block* block = NULL; Cache::Handle* cache_handle = NULL; @@ -176,6 +178,8 @@ Iterator* Table::BlockReader(void* arg, cache_handle = block_cache->Lookup(key); if (cache_handle != NULL) { block = reinterpret_cast(block_cache->Value(cache_handle)); + + RecordTick(statistics, BLOCK_CACHE_HIT); } else { s = ReadBlock(table->rep_->file, options, handle, &contents); if (s.ok()) { @@ -188,6 +192,8 @@ Iterator* Table::BlockReader(void* arg, if (didIO != NULL) { *didIO = true; // we did some io from storage } + + RecordTick(statistics, BLOCK_CACHE_MISS); } } else { s = ReadBlock(table->rep_->file, options, handle, &contents); -- GitLab