From e542ef76fb9e5b167746773355fb603177564918 Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Wed, 26 Sep 2018 18:00:18 -0700 Subject: [PATCH] ircd::db: Add per-cache statistics. --- include/ircd/db/cache.h | 18 +--- include/ircd/db/database/cache.h | 2 +- include/ircd/db/database/stats.h | 32 ++++++- ircd/db.cc | 153 +++++++++++++++++++++++++++---- 4 files changed, 168 insertions(+), 37 deletions(-) diff --git a/include/ircd/db/cache.h b/include/ircd/db/cache.h index aa79f7734..5d357dd18 100644 --- a/include/ircd/db/cache.h +++ b/include/ircd/db/cache.h @@ -21,11 +21,9 @@ namespace ircd::db { - struct cache_stats; - - // Get our stats - const cache_stats &stats(const rocksdb::Cache &); - cache_stats stats(const rocksdb::Cache *const &); + // Get our stats; refer to db/stats.h for ticker ID related. + const uint64_t &ticker(const rocksdb::Cache &, const uint32_t &ticker_id); + uint64_t ticker(const rocksdb::Cache *const &, const uint32_t &ticker_id); // Get capacity size_t capacity(const rocksdb::Cache &); @@ -68,13 +66,3 @@ namespace ircd::db void clear(rocksdb::Cache &); void clear(rocksdb::Cache *const &); } - -/// Our custom cache statistics. Though the rocksdb::Statistics ticker could -/// be instantiated for each cache we have our own counters, and we let the -/// rocksdb cache impl update our database ticker instead for aggregate stats. -struct ircd::db::cache_stats -{ - size_t inserts {0}; - size_t misses {0}; - size_t hits {0}; -}; diff --git a/include/ircd/db/database/cache.h b/include/ircd/db/database/cache.h index d365d6b29..2ff244556 100644 --- a/include/ircd/db/database/cache.h +++ b/include/ircd/db/database/cache.h @@ -34,8 +34,8 @@ final static const bool DEFAULT_STRICT; database *d; - cache_stats stats; std::shared_ptr c; + struct database::stats stats; const char *Name() const noexcept override; Status Insert(const Slice &key, void *value, size_t charge, deleter, Handle **, Priority) noexcept override; diff --git a/include/ircd/db/database/stats.h b/include/ircd/db/database/stats.h index a2371a181..bd2e7f122 100644 --- a/include/ircd/db/database/stats.h +++ b/include/ircd/db/database/stats.h @@ -15,11 +15,13 @@ // RocksDB symbols which we cannot forward declare. It is used internally // and does not need to be included by general users of IRCd. -struct ircd::db::database::stats final -:std::enable_shared_from_this -,rocksdb::Statistics +struct ircd::db::database::stats +final +:rocksdb::Statistics { - database *d; + struct passthru; + + database *d {nullptr}; std::array ticker {{0}}; std::array histogram; @@ -32,5 +34,25 @@ struct ircd::db::database::stats final uint64_t getAndResetTickerCount(const uint32_t tickerType) noexcept override; rocksdb::Status Reset() noexcept override; - stats(database *const &d); + stats(database *const &d = nullptr); + ~stats() noexcept; +}; + +struct ircd::db::database::stats::passthru +final +:rocksdb::Statistics +{ + std::array pass {{nullptr}}; + + void recordTick(const uint32_t tickerType, const uint64_t count) noexcept override; + void measureTime(const uint32_t histogramType, const uint64_t time) noexcept override; + bool HistEnabledForType(const uint32_t type) const noexcept override; + uint64_t getTickerCount(const uint32_t tickerType) const noexcept override; + void setTickerCount(const uint32_t tickerType, const uint64_t count) noexcept override; + void histogramData(const uint32_t type, rocksdb::HistogramData *) const noexcept override; + uint64_t getAndResetTickerCount(const uint32_t tickerType) noexcept override; + rocksdb::Status Reset() noexcept override; + + passthru(rocksdb::Statistics *const &a, rocksdb::Statistics *const &b); + ~passthru() noexcept; }; diff --git a/ircd/db.cc b/ircd/db.cc index a3bc263a9..c9ca7c555 100644 --- a/ircd/db.cc +++ b/ircd/db.cc @@ -1906,11 +1906,20 @@ ircd::db::histogram_max // database::stats (db/database/stats.h) internal // +// +// stats::stats +// + ircd::db::database::stats::stats(database *const &d) :d{d} { } +ircd::db::database::stats::~stats() +noexcept +{ +} + rocksdb::Status ircd::db::database::stats::Reset() noexcept @@ -1992,6 +2001,95 @@ const noexcept return ticker.at(type); } +// +// database::stats::passthru +// + +ircd::db::database::stats::passthru::passthru(rocksdb::Statistics *const &a, + rocksdb::Statistics *const &b) +:pass +{ + { a, b } +} +{ +} + +ircd::db::database::stats::passthru::~passthru() +noexcept +{ +} + +[[noreturn]] +rocksdb::Status +ircd::db::database::stats::passthru::Reset() +noexcept +{ + throw assertive {"Unavailable for passthru"}; +} + +void +ircd::db::database::stats::passthru::recordTick(const uint32_t tickerType, + const uint64_t count) +noexcept +{ + for(auto *const &pass : this->pass) + pass->recordTick(tickerType, count); +} + +void +ircd::db::database::stats::passthru::measureTime(const uint32_t histogramType, + const uint64_t time) +noexcept +{ + for(auto *const &pass : this->pass) + pass->measureTime(histogramType, time); +} + +bool +ircd::db::database::stats::passthru::HistEnabledForType(const uint32_t type) +const noexcept +{ + return std::all_of(begin(pass), end(pass), [&type] + (const auto *const &pass) + { + return pass->HistEnabledForType(type); + }); +} + +[[noreturn]] +uint64_t +ircd::db::database::stats::passthru::getTickerCount(const uint32_t tickerType) +const noexcept +{ + throw assertive {"Unavailable for passthru"}; +} + +[[noreturn]] +void +ircd::db::database::stats::passthru::setTickerCount(const uint32_t tickerType, + const uint64_t count) +noexcept +{ + throw assertive {"Unavailable for passthru"}; +} + +[[noreturn]] +void +ircd::db::database::stats::passthru::histogramData(const uint32_t type, + rocksdb::HistogramData *const data) +const noexcept +{ + throw assertive {"Unavailable for passthru"}; +} + +[[noreturn]] +uint64_t +ircd::db::database::stats::passthru::getAndResetTickerCount(const uint32_t tickerType) +noexcept +{ + throw assertive {"Unavailable for passthru"}; +} + /////////////////////////////////////////////////////////////////////////////// // // database::events @@ -2246,13 +2344,15 @@ ircd::db::database::cache::cache(database *const &d, { rocksdb::NewLRUCache ( - std::max(initial_capacity, ssize_t(0)), - DEFAULT_SHARD_BITS, - DEFAULT_STRICT, - DEFAULT_HI_PRIO + std::max(initial_capacity, ssize_t(0)) + ,DEFAULT_SHARD_BITS + ,DEFAULT_STRICT + ,DEFAULT_HI_PRIO ) } +,stats{d} { + assert(bool(c)); } ircd::db::database::cache::~cache() @@ -2283,7 +2383,9 @@ noexcept c->Insert(key, value, charge, del, handle, priority) }; - stats.inserts += ret.ok(); + this->stats.recordTick(rocksdb::Tickers::BLOCK_CACHE_ADD, ret.ok()); + this->stats.recordTick(rocksdb::Tickers::BLOCK_CACHE_ADD_FAILURES, !ret.ok()); + this->stats.recordTick(rocksdb::Tickers::BLOCK_CACHE_DATA_BYTES_INSERT, ret.ok()? charge : 0UL); return ret; } @@ -2293,13 +2395,30 @@ ircd::db::database::cache::Lookup(const Slice &key, noexcept { assert(bool(c)); - auto *const &ret + + database::stats::passthru passthru { - c->Lookup(key, statistics) + &this->stats, statistics }; - stats.hits += bool(ret); - stats.misses += !bool(ret); + rocksdb::Statistics *const s + { + statistics? + dynamic_cast(&passthru): + dynamic_cast(&this->stats) + }; + + auto *const &ret + { + c->Lookup(key, s) + }; + + // Rocksdb's LRUCache stats are broke. The statistics ptr is null and + // passing it to Lookup() does nothing internally. We have to do this + // here ourselves :/ + + this->stats.recordTick(rocksdb::Tickers::BLOCK_CACHE_HIT, bool(ret)); + this->stats.recordTick(rocksdb::Tickers::BLOCK_CACHE_MISS, !bool(ret)); return ret; } @@ -8885,21 +9004,23 @@ ircd::db::capacity(const rocksdb::Cache &cache) return cache.GetCapacity(); } -ircd::db::cache_stats -ircd::db::stats(const rocksdb::Cache *const &cache) +uint64_t +ircd::db::ticker(const rocksdb::Cache *const &cache, + const uint32_t &ticker_id) { - return cache? stats(*cache) : cache_stats{}; + return cache? ticker(*cache, ticker_id) : 0UL; } -const ircd::db::cache_stats & -ircd::db::stats(const rocksdb::Cache &cache) +const uint64_t & +ircd::db::ticker(const rocksdb::Cache &cache, + const uint32_t &ticker_id) { - const auto &dc + const auto &c { dynamic_cast(cache) }; - return dc.stats; + return c.stats.ticker.at(ticker_id); } ///////////////////////////////////////////////////////////////////////////////