2012-05-30 08:18:16 +02:00
|
|
|
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
|
|
|
|
// 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.
|
|
|
|
|
|
|
|
#ifndef STORAGE_LEVELDB_INCLUDE_STATISTICS_H_
|
|
|
|
#define STORAGE_LEVELDB_INCLUDE_STATISTICS_H_
|
|
|
|
|
2013-05-10 22:19:39 +02:00
|
|
|
#include <atomic>
|
2013-06-10 20:57:55 +02:00
|
|
|
#include <cassert>
|
2013-02-15 20:53:17 +01:00
|
|
|
#include <cstddef>
|
|
|
|
#include <cstdint>
|
|
|
|
#include <string>
|
|
|
|
#include <memory>
|
2013-06-10 20:57:55 +02:00
|
|
|
#include <vector>
|
2013-02-15 20:53:17 +01:00
|
|
|
|
2012-05-30 08:18:16 +02:00
|
|
|
namespace leveldb {
|
|
|
|
|
2012-11-03 05:02:40 +01:00
|
|
|
/**
|
|
|
|
* 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
|
2013-06-10 20:57:55 +02:00
|
|
|
* Add a string representation in TickersNameMap below.
|
2012-11-03 05:02:40 +01:00
|
|
|
* And incrementing TICKER_ENUM_MAX.
|
|
|
|
*/
|
|
|
|
enum Tickers {
|
|
|
|
BLOCK_CACHE_MISS = 0,
|
|
|
|
BLOCK_CACHE_HIT = 1,
|
2012-11-09 03:18:34 +01:00
|
|
|
BLOOM_FILTER_USEFUL = 2, // no. of times bloom filter has avoided file reads.
|
|
|
|
/**
|
|
|
|
* COMPACTION_KEY_DROP_* count the reasons for key drop during compaction
|
|
|
|
* There are 3 reasons currently.
|
|
|
|
*/
|
|
|
|
COMPACTION_KEY_DROP_NEWER_ENTRY = 3, // key was written with a newer value.
|
|
|
|
COMPACTION_KEY_DROP_OBSOLETE = 4, // The key is obsolete.
|
|
|
|
COMPACTION_KEY_DROP_USER = 5, // user compaction function has dropped the key.
|
2013-01-16 01:48:22 +01:00
|
|
|
// Number of keys written to the database via the Put and Write call's
|
|
|
|
NUMBER_KEYS_WRITTEN = 6,
|
|
|
|
// Number of Keys read,
|
|
|
|
NUMBER_KEYS_READ = 7,
|
2013-02-21 04:22:13 +01:00
|
|
|
// Bytes written / read
|
|
|
|
BYTES_WRITTEN = 8,
|
|
|
|
BYTES_READ = 9,
|
2013-02-25 22:58:34 +01:00
|
|
|
NO_FILE_CLOSES = 10,
|
|
|
|
NO_FILE_OPENS = 11,
|
|
|
|
NO_FILE_ERRORS = 12,
|
2013-05-10 23:41:45 +02:00
|
|
|
// Time system had to wait to do LO-L1 compactions
|
|
|
|
STALL_L0_SLOWDOWN_MICROS = 13,
|
|
|
|
// Time system had to wait to move memtable to L1.
|
|
|
|
STALL_MEMTABLE_COMPACTION_MICROS = 14,
|
|
|
|
// write throttle because of too many files in L0
|
|
|
|
STALL_L0_NUM_FILES_MICROS = 15,
|
|
|
|
RATE_LIMIT_DELAY_MILLIS = 16,
|
2013-06-05 20:22:38 +02:00
|
|
|
|
2013-05-28 23:00:10 +02:00
|
|
|
NO_ITERATORS = 17, // number of iterators currently open
|
2013-06-05 20:22:38 +02:00
|
|
|
|
|
|
|
// Number of MultiGet calls, keys read, and bytes read
|
|
|
|
NUMBER_MULTIGET_CALLS = 18,
|
|
|
|
NUMBER_MULTIGET_KEYS_READ = 19,
|
|
|
|
NUMBER_MULTIGET_BYTES_READ = 20,
|
|
|
|
|
2013-07-06 03:49:18 +02:00
|
|
|
NUMBER_FILTERED_DELETES = 21,
|
|
|
|
|
|
|
|
TICKER_ENUM_MAX = 22
|
2012-11-03 05:02:40 +01:00
|
|
|
};
|
|
|
|
|
2013-06-10 20:57:55 +02:00
|
|
|
const std::vector<std::pair<Tickers, std::string>> TickersNameMap = {
|
2013-06-19 21:39:24 +02:00
|
|
|
{ BLOCK_CACHE_MISS, "rocksdb.block.cache.miss" },
|
|
|
|
{ BLOCK_CACHE_HIT, "rocksdb.block.cache.hit" },
|
|
|
|
{ BLOOM_FILTER_USEFUL, "rocksdb.bloom.filter.useful" },
|
|
|
|
{ COMPACTION_KEY_DROP_NEWER_ENTRY, "rocksdb.compaction.key.drop.new" },
|
|
|
|
{ COMPACTION_KEY_DROP_OBSOLETE, "rocksdb.compaction.key.drop.obsolete" },
|
|
|
|
{ COMPACTION_KEY_DROP_USER, "rocksdb.compaction.key.drop.user" },
|
|
|
|
{ NUMBER_KEYS_WRITTEN, "rocksdb.number.keys.written" },
|
|
|
|
{ NUMBER_KEYS_READ, "rocksdb.number.keys.read" },
|
|
|
|
{ BYTES_WRITTEN, "rocksdb.bytes.written" },
|
|
|
|
{ BYTES_READ, "rocksdb.bytes.read" },
|
|
|
|
{ NO_FILE_CLOSES, "rocksdb.no.file.closes" },
|
|
|
|
{ NO_FILE_OPENS, "rocksdb.no.file.opens" },
|
|
|
|
{ NO_FILE_ERRORS, "rocksdb.no.file.errors" },
|
|
|
|
{ STALL_L0_SLOWDOWN_MICROS, "rocksdb.l0.slowdown.micros" },
|
|
|
|
{ STALL_MEMTABLE_COMPACTION_MICROS, "rocksdb.memtable.compaction.micros" },
|
|
|
|
{ STALL_L0_NUM_FILES_MICROS, "rocksdb.l0.num.files.stall.micros" },
|
|
|
|
{ RATE_LIMIT_DELAY_MILLIS, "rocksdb.rate.limit.dleay.millis" },
|
|
|
|
{ NO_ITERATORS, "rocksdb.num.iterators" },
|
|
|
|
{ NUMBER_MULTIGET_CALLS, "rocksdb.number.multiget.get" },
|
|
|
|
{ NUMBER_MULTIGET_KEYS_READ, "rocksdb.number.multiget.keys.read" },
|
2013-07-06 03:49:18 +02:00
|
|
|
{ NUMBER_MULTIGET_BYTES_READ, "rocksdb.number.multiget.bytes.read" },
|
|
|
|
{ NUMBER_FILTERED_DELETES, "rocksdb.number.deletes.filtered" }
|
2013-06-10 20:57:55 +02:00
|
|
|
};
|
2013-02-21 04:22:13 +01:00
|
|
|
|
2013-02-15 20:53:17 +01:00
|
|
|
/**
|
|
|
|
* Keep adding histogram's here.
|
|
|
|
* Any histogram whould have value less than HISTOGRAM_ENUM_MAX
|
|
|
|
* Add a new Histogram by assigning it the current value of HISTOGRAM_ENUM_MAX
|
2013-06-10 20:57:55 +02:00
|
|
|
* Add a string representation in HistogramsNameMap below
|
2013-02-15 20:53:17 +01:00
|
|
|
* And increment HISTOGRAM_ENUM_MAX
|
|
|
|
*/
|
|
|
|
enum Histograms {
|
|
|
|
DB_GET = 0,
|
|
|
|
DB_WRITE = 1,
|
2013-02-22 01:23:33 +01:00
|
|
|
COMPACTION_TIME = 2,
|
2013-06-05 20:06:21 +02:00
|
|
|
TABLE_SYNC_MICROS = 3,
|
|
|
|
COMPACTION_OUTFILE_SYNC_MICROS = 4,
|
|
|
|
WAL_FILE_SYNC_MICROS = 5,
|
|
|
|
MANIFEST_FILE_SYNC_MICROS = 6,
|
2013-06-07 19:02:28 +02:00
|
|
|
// TIME SPENT IN IO DURING TABLE OPEN
|
|
|
|
TABLE_OPEN_IO_MICROS = 7,
|
|
|
|
DB_MULTIGET = 8,
|
2013-06-14 02:25:09 +02:00
|
|
|
READ_BLOCK_COMPACTION_MICROS = 9,
|
|
|
|
READ_BLOCK_GET_MICROS = 10,
|
2013-06-17 19:11:10 +02:00
|
|
|
WRITE_RAW_BLOCK_MICROS = 11,
|
|
|
|
HISTOGRAM_ENUM_MAX = 12
|
2013-02-15 20:53:17 +01:00
|
|
|
};
|
|
|
|
|
2013-06-10 20:57:55 +02:00
|
|
|
const std::vector<std::pair<Histograms, std::string>> HistogramsNameMap = {
|
2013-06-19 21:39:24 +02:00
|
|
|
{ DB_GET, "rocksdb.db.get.micros" },
|
|
|
|
{ DB_WRITE, "rocksdb.db.write.micros" },
|
|
|
|
{ COMPACTION_TIME, "rocksdb.compaction.times.micros" },
|
|
|
|
{ TABLE_SYNC_MICROS, "rocksdb.table.sync.micros" },
|
|
|
|
{ COMPACTION_OUTFILE_SYNC_MICROS, "rocksdb.compaction.outfile.sync.micros" },
|
|
|
|
{ WAL_FILE_SYNC_MICROS, "rocksdb.wal.file.sync.micros" },
|
|
|
|
{ MANIFEST_FILE_SYNC_MICROS, "rocksdb.manifest.file.sync.micros" },
|
|
|
|
{ TABLE_OPEN_IO_MICROS, "rocksdb.table.open.io.micros" },
|
|
|
|
{ DB_MULTIGET, "rocksdb.db.multiget.micros" },
|
|
|
|
{ READ_BLOCK_COMPACTION_MICROS, "rocksdb.read.block.compaction.micros" },
|
|
|
|
{ READ_BLOCK_GET_MICROS, "rocksdb.read.block.get.micros" },
|
|
|
|
{ WRITE_RAW_BLOCK_MICROS, "rocksdb.write.raw.block.micros" }
|
2013-06-10 20:57:55 +02:00
|
|
|
};
|
|
|
|
|
2013-02-15 20:53:17 +01:00
|
|
|
struct HistogramData {
|
|
|
|
double median;
|
|
|
|
double percentile95;
|
|
|
|
double percentile99;
|
|
|
|
double average;
|
|
|
|
double standard_deviation;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class Histogram {
|
|
|
|
public:
|
|
|
|
// clear's the histogram
|
|
|
|
virtual void Clear() = 0;
|
|
|
|
virtual ~Histogram();
|
|
|
|
// Add a value to be recorded in the histogram.
|
|
|
|
virtual void Add(uint64_t value) = 0;
|
|
|
|
|
|
|
|
virtual std::string ToString() const = 0;
|
|
|
|
|
|
|
|
// Get statistics
|
|
|
|
virtual double Median() const = 0;
|
|
|
|
virtual double Percentile(double p) const = 0;
|
|
|
|
virtual double Average() const = 0;
|
|
|
|
virtual double StandardDeviation() const = 0;
|
|
|
|
virtual void Data(HistogramData * const data) const = 0;
|
|
|
|
|
|
|
|
};
|
2012-11-03 05:02:40 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 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) { }
|
|
|
|
|
2013-06-10 20:57:55 +02:00
|
|
|
inline void recordTick() {
|
2012-11-03 05:02:40 +01:00
|
|
|
count_++;
|
|
|
|
}
|
|
|
|
|
2013-01-16 01:48:22 +01:00
|
|
|
inline void recordTick(int count) {
|
|
|
|
count_ += count;
|
|
|
|
}
|
2013-02-15 20:53:17 +01:00
|
|
|
|
2012-11-03 05:02:40 +01:00
|
|
|
inline uint64_t getCount() {
|
|
|
|
return count_;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2013-05-10 22:19:39 +02:00
|
|
|
std::atomic_uint_fast64_t count_;
|
2012-11-03 05:02:40 +01:00
|
|
|
};
|
|
|
|
|
2012-05-30 08:18:16 +02:00
|
|
|
// Analyze the performance of a db
|
|
|
|
class Statistics {
|
2012-11-03 05:02:40 +01:00
|
|
|
public:
|
2012-05-30 08:18:16 +02:00
|
|
|
|
2012-11-03 05:02:40 +01:00
|
|
|
virtual long getTickerCount(Tickers tickerType) = 0;
|
2013-01-16 01:48:22 +01:00
|
|
|
virtual void recordTick(Tickers tickerType, uint64_t count = 0) = 0;
|
2013-05-16 19:40:30 +02:00
|
|
|
virtual void measureTime(Histograms histogramType, uint64_t time) = 0;
|
2013-02-15 20:53:17 +01:00
|
|
|
|
|
|
|
virtual void histogramData(Histograms type, HistogramData * const data) = 0;
|
2013-06-19 05:28:41 +02:00
|
|
|
// String representation of the statistic object.
|
|
|
|
std::string ToString();
|
2012-05-30 08:18:16 +02:00
|
|
|
};
|
|
|
|
|
2013-05-23 20:34:58 +02:00
|
|
|
// Create a concrete DBStatistics object
|
|
|
|
std::shared_ptr<Statistics> CreateDBStatistics();
|
|
|
|
|
2012-11-03 05:02:40 +01:00
|
|
|
// Ease of Use functions
|
2013-03-27 19:27:39 +01:00
|
|
|
inline void RecordTick(std::shared_ptr<Statistics> statistics,
|
2013-01-16 01:48:22 +01:00
|
|
|
Tickers ticker,
|
|
|
|
uint64_t count = 1) {
|
2013-06-10 22:14:14 +02:00
|
|
|
assert(HistogramsNameMap.size() == HISTOGRAM_ENUM_MAX);
|
|
|
|
assert(TickersNameMap.size() == TICKER_ENUM_MAX);
|
2013-03-27 19:27:39 +01:00
|
|
|
if (statistics) {
|
2013-01-16 01:48:22 +01:00
|
|
|
statistics->recordTick(ticker, count);
|
2012-11-03 05:02:40 +01:00
|
|
|
}
|
2013-01-16 01:48:22 +01:00
|
|
|
}
|
2012-05-30 08:18:16 +02:00
|
|
|
} // namespace leveldb
|
|
|
|
|
|
|
|
#endif // STORAGE_LEVELDB_INCLUDE_STATISTICS_H_
|