statistics.cc 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
  2. // This source code is licensed under both the GPLv2 (found in the
  3. // COPYING file in the root directory) and Apache 2.0 License
  4. // (found in the LICENSE.Apache file in the root directory).
  5. //
  6. #include "monitoring/statistics.h"
  7. #include <algorithm>
  8. #include <cinttypes>
  9. #include <cstdio>
  10. #include "port/likely.h"
  11. #include "rocksdb/statistics.h"
  12. namespace ROCKSDB_NAMESPACE {
  13. // The order of items listed in Tickers should be the same as
  14. // the order listed in TickersNameMap
  15. const std::vector<std::pair<Tickers, std::string>> TickersNameMap = {
  16. {BLOCK_CACHE_MISS, "rocksdb.block.cache.miss"},
  17. {BLOCK_CACHE_HIT, "rocksdb.block.cache.hit"},
  18. {BLOCK_CACHE_ADD, "rocksdb.block.cache.add"},
  19. {BLOCK_CACHE_ADD_FAILURES, "rocksdb.block.cache.add.failures"},
  20. {BLOCK_CACHE_INDEX_MISS, "rocksdb.block.cache.index.miss"},
  21. {BLOCK_CACHE_INDEX_HIT, "rocksdb.block.cache.index.hit"},
  22. {BLOCK_CACHE_INDEX_ADD, "rocksdb.block.cache.index.add"},
  23. {BLOCK_CACHE_INDEX_BYTES_INSERT, "rocksdb.block.cache.index.bytes.insert"},
  24. {BLOCK_CACHE_INDEX_BYTES_EVICT, "rocksdb.block.cache.index.bytes.evict"},
  25. {BLOCK_CACHE_FILTER_MISS, "rocksdb.block.cache.filter.miss"},
  26. {BLOCK_CACHE_FILTER_HIT, "rocksdb.block.cache.filter.hit"},
  27. {BLOCK_CACHE_FILTER_ADD, "rocksdb.block.cache.filter.add"},
  28. {BLOCK_CACHE_FILTER_BYTES_INSERT,
  29. "rocksdb.block.cache.filter.bytes.insert"},
  30. {BLOCK_CACHE_FILTER_BYTES_EVICT, "rocksdb.block.cache.filter.bytes.evict"},
  31. {BLOCK_CACHE_DATA_MISS, "rocksdb.block.cache.data.miss"},
  32. {BLOCK_CACHE_DATA_HIT, "rocksdb.block.cache.data.hit"},
  33. {BLOCK_CACHE_DATA_ADD, "rocksdb.block.cache.data.add"},
  34. {BLOCK_CACHE_DATA_BYTES_INSERT, "rocksdb.block.cache.data.bytes.insert"},
  35. {BLOCK_CACHE_BYTES_READ, "rocksdb.block.cache.bytes.read"},
  36. {BLOCK_CACHE_BYTES_WRITE, "rocksdb.block.cache.bytes.write"},
  37. {BLOOM_FILTER_USEFUL, "rocksdb.bloom.filter.useful"},
  38. {BLOOM_FILTER_FULL_POSITIVE, "rocksdb.bloom.filter.full.positive"},
  39. {BLOOM_FILTER_FULL_TRUE_POSITIVE,
  40. "rocksdb.bloom.filter.full.true.positive"},
  41. {BLOOM_FILTER_MICROS, "rocksdb.bloom.filter.micros"},
  42. {PERSISTENT_CACHE_HIT, "rocksdb.persistent.cache.hit"},
  43. {PERSISTENT_CACHE_MISS, "rocksdb.persistent.cache.miss"},
  44. {SIM_BLOCK_CACHE_HIT, "rocksdb.sim.block.cache.hit"},
  45. {SIM_BLOCK_CACHE_MISS, "rocksdb.sim.block.cache.miss"},
  46. {MEMTABLE_HIT, "rocksdb.memtable.hit"},
  47. {MEMTABLE_MISS, "rocksdb.memtable.miss"},
  48. {GET_HIT_L0, "rocksdb.l0.hit"},
  49. {GET_HIT_L1, "rocksdb.l1.hit"},
  50. {GET_HIT_L2_AND_UP, "rocksdb.l2andup.hit"},
  51. {COMPACTION_KEY_DROP_NEWER_ENTRY, "rocksdb.compaction.key.drop.new"},
  52. {COMPACTION_KEY_DROP_OBSOLETE, "rocksdb.compaction.key.drop.obsolete"},
  53. {COMPACTION_KEY_DROP_RANGE_DEL, "rocksdb.compaction.key.drop.range_del"},
  54. {COMPACTION_KEY_DROP_USER, "rocksdb.compaction.key.drop.user"},
  55. {COMPACTION_RANGE_DEL_DROP_OBSOLETE,
  56. "rocksdb.compaction.range_del.drop.obsolete"},
  57. {COMPACTION_OPTIMIZED_DEL_DROP_OBSOLETE,
  58. "rocksdb.compaction.optimized.del.drop.obsolete"},
  59. {COMPACTION_CANCELLED, "rocksdb.compaction.cancelled"},
  60. {NUMBER_KEYS_WRITTEN, "rocksdb.number.keys.written"},
  61. {NUMBER_KEYS_READ, "rocksdb.number.keys.read"},
  62. {NUMBER_KEYS_UPDATED, "rocksdb.number.keys.updated"},
  63. {BYTES_WRITTEN, "rocksdb.bytes.written"},
  64. {BYTES_READ, "rocksdb.bytes.read"},
  65. {NUMBER_DB_SEEK, "rocksdb.number.db.seek"},
  66. {NUMBER_DB_NEXT, "rocksdb.number.db.next"},
  67. {NUMBER_DB_PREV, "rocksdb.number.db.prev"},
  68. {NUMBER_DB_SEEK_FOUND, "rocksdb.number.db.seek.found"},
  69. {NUMBER_DB_NEXT_FOUND, "rocksdb.number.db.next.found"},
  70. {NUMBER_DB_PREV_FOUND, "rocksdb.number.db.prev.found"},
  71. {ITER_BYTES_READ, "rocksdb.db.iter.bytes.read"},
  72. {NO_FILE_CLOSES, "rocksdb.no.file.closes"},
  73. {NO_FILE_OPENS, "rocksdb.no.file.opens"},
  74. {NO_FILE_ERRORS, "rocksdb.no.file.errors"},
  75. {STALL_L0_SLOWDOWN_MICROS, "rocksdb.l0.slowdown.micros"},
  76. {STALL_MEMTABLE_COMPACTION_MICROS, "rocksdb.memtable.compaction.micros"},
  77. {STALL_L0_NUM_FILES_MICROS, "rocksdb.l0.num.files.stall.micros"},
  78. {STALL_MICROS, "rocksdb.stall.micros"},
  79. {DB_MUTEX_WAIT_MICROS, "rocksdb.db.mutex.wait.micros"},
  80. {RATE_LIMIT_DELAY_MILLIS, "rocksdb.rate.limit.delay.millis"},
  81. {NO_ITERATORS, "rocksdb.num.iterators"},
  82. {NUMBER_MULTIGET_CALLS, "rocksdb.number.multiget.get"},
  83. {NUMBER_MULTIGET_KEYS_READ, "rocksdb.number.multiget.keys.read"},
  84. {NUMBER_MULTIGET_BYTES_READ, "rocksdb.number.multiget.bytes.read"},
  85. {NUMBER_FILTERED_DELETES, "rocksdb.number.deletes.filtered"},
  86. {NUMBER_MERGE_FAILURES, "rocksdb.number.merge.failures"},
  87. {BLOOM_FILTER_PREFIX_CHECKED, "rocksdb.bloom.filter.prefix.checked"},
  88. {BLOOM_FILTER_PREFIX_USEFUL, "rocksdb.bloom.filter.prefix.useful"},
  89. {NUMBER_OF_RESEEKS_IN_ITERATION, "rocksdb.number.reseeks.iteration"},
  90. {GET_UPDATES_SINCE_CALLS, "rocksdb.getupdatessince.calls"},
  91. {BLOCK_CACHE_COMPRESSED_MISS, "rocksdb.block.cachecompressed.miss"},
  92. {BLOCK_CACHE_COMPRESSED_HIT, "rocksdb.block.cachecompressed.hit"},
  93. {BLOCK_CACHE_COMPRESSED_ADD, "rocksdb.block.cachecompressed.add"},
  94. {BLOCK_CACHE_COMPRESSED_ADD_FAILURES,
  95. "rocksdb.block.cachecompressed.add.failures"},
  96. {WAL_FILE_SYNCED, "rocksdb.wal.synced"},
  97. {WAL_FILE_BYTES, "rocksdb.wal.bytes"},
  98. {WRITE_DONE_BY_SELF, "rocksdb.write.self"},
  99. {WRITE_DONE_BY_OTHER, "rocksdb.write.other"},
  100. {WRITE_TIMEDOUT, "rocksdb.write.timeout"},
  101. {WRITE_WITH_WAL, "rocksdb.write.wal"},
  102. {COMPACT_READ_BYTES, "rocksdb.compact.read.bytes"},
  103. {COMPACT_WRITE_BYTES, "rocksdb.compact.write.bytes"},
  104. {FLUSH_WRITE_BYTES, "rocksdb.flush.write.bytes"},
  105. {NUMBER_DIRECT_LOAD_TABLE_PROPERTIES,
  106. "rocksdb.number.direct.load.table.properties"},
  107. {NUMBER_SUPERVERSION_ACQUIRES, "rocksdb.number.superversion_acquires"},
  108. {NUMBER_SUPERVERSION_RELEASES, "rocksdb.number.superversion_releases"},
  109. {NUMBER_SUPERVERSION_CLEANUPS, "rocksdb.number.superversion_cleanups"},
  110. {NUMBER_BLOCK_COMPRESSED, "rocksdb.number.block.compressed"},
  111. {NUMBER_BLOCK_DECOMPRESSED, "rocksdb.number.block.decompressed"},
  112. {NUMBER_BLOCK_NOT_COMPRESSED, "rocksdb.number.block.not_compressed"},
  113. {MERGE_OPERATION_TOTAL_TIME, "rocksdb.merge.operation.time.nanos"},
  114. {FILTER_OPERATION_TOTAL_TIME, "rocksdb.filter.operation.time.nanos"},
  115. {ROW_CACHE_HIT, "rocksdb.row.cache.hit"},
  116. {ROW_CACHE_MISS, "rocksdb.row.cache.miss"},
  117. {READ_AMP_ESTIMATE_USEFUL_BYTES, "rocksdb.read.amp.estimate.useful.bytes"},
  118. {READ_AMP_TOTAL_READ_BYTES, "rocksdb.read.amp.total.read.bytes"},
  119. {NUMBER_RATE_LIMITER_DRAINS, "rocksdb.number.rate_limiter.drains"},
  120. {NUMBER_ITER_SKIP, "rocksdb.number.iter.skip"},
  121. {BLOB_DB_NUM_PUT, "rocksdb.blobdb.num.put"},
  122. {BLOB_DB_NUM_WRITE, "rocksdb.blobdb.num.write"},
  123. {BLOB_DB_NUM_GET, "rocksdb.blobdb.num.get"},
  124. {BLOB_DB_NUM_MULTIGET, "rocksdb.blobdb.num.multiget"},
  125. {BLOB_DB_NUM_SEEK, "rocksdb.blobdb.num.seek"},
  126. {BLOB_DB_NUM_NEXT, "rocksdb.blobdb.num.next"},
  127. {BLOB_DB_NUM_PREV, "rocksdb.blobdb.num.prev"},
  128. {BLOB_DB_NUM_KEYS_WRITTEN, "rocksdb.blobdb.num.keys.written"},
  129. {BLOB_DB_NUM_KEYS_READ, "rocksdb.blobdb.num.keys.read"},
  130. {BLOB_DB_BYTES_WRITTEN, "rocksdb.blobdb.bytes.written"},
  131. {BLOB_DB_BYTES_READ, "rocksdb.blobdb.bytes.read"},
  132. {BLOB_DB_WRITE_INLINED, "rocksdb.blobdb.write.inlined"},
  133. {BLOB_DB_WRITE_INLINED_TTL, "rocksdb.blobdb.write.inlined.ttl"},
  134. {BLOB_DB_WRITE_BLOB, "rocksdb.blobdb.write.blob"},
  135. {BLOB_DB_WRITE_BLOB_TTL, "rocksdb.blobdb.write.blob.ttl"},
  136. {BLOB_DB_BLOB_FILE_BYTES_WRITTEN, "rocksdb.blobdb.blob.file.bytes.written"},
  137. {BLOB_DB_BLOB_FILE_BYTES_READ, "rocksdb.blobdb.blob.file.bytes.read"},
  138. {BLOB_DB_BLOB_FILE_SYNCED, "rocksdb.blobdb.blob.file.synced"},
  139. {BLOB_DB_BLOB_INDEX_EXPIRED_COUNT,
  140. "rocksdb.blobdb.blob.index.expired.count"},
  141. {BLOB_DB_BLOB_INDEX_EXPIRED_SIZE, "rocksdb.blobdb.blob.index.expired.size"},
  142. {BLOB_DB_BLOB_INDEX_EVICTED_COUNT,
  143. "rocksdb.blobdb.blob.index.evicted.count"},
  144. {BLOB_DB_BLOB_INDEX_EVICTED_SIZE, "rocksdb.blobdb.blob.index.evicted.size"},
  145. {BLOB_DB_GC_NUM_FILES, "rocksdb.blobdb.gc.num.files"},
  146. {BLOB_DB_GC_NUM_NEW_FILES, "rocksdb.blobdb.gc.num.new.files"},
  147. {BLOB_DB_GC_FAILURES, "rocksdb.blobdb.gc.failures"},
  148. {BLOB_DB_GC_NUM_KEYS_OVERWRITTEN, "rocksdb.blobdb.gc.num.keys.overwritten"},
  149. {BLOB_DB_GC_NUM_KEYS_EXPIRED, "rocksdb.blobdb.gc.num.keys.expired"},
  150. {BLOB_DB_GC_NUM_KEYS_RELOCATED, "rocksdb.blobdb.gc.num.keys.relocated"},
  151. {BLOB_DB_GC_BYTES_OVERWRITTEN, "rocksdb.blobdb.gc.bytes.overwritten"},
  152. {BLOB_DB_GC_BYTES_EXPIRED, "rocksdb.blobdb.gc.bytes.expired"},
  153. {BLOB_DB_GC_BYTES_RELOCATED, "rocksdb.blobdb.gc.bytes.relocated"},
  154. {BLOB_DB_FIFO_NUM_FILES_EVICTED, "rocksdb.blobdb.fifo.num.files.evicted"},
  155. {BLOB_DB_FIFO_NUM_KEYS_EVICTED, "rocksdb.blobdb.fifo.num.keys.evicted"},
  156. {BLOB_DB_FIFO_BYTES_EVICTED, "rocksdb.blobdb.fifo.bytes.evicted"},
  157. {TXN_PREPARE_MUTEX_OVERHEAD, "rocksdb.txn.overhead.mutex.prepare"},
  158. {TXN_OLD_COMMIT_MAP_MUTEX_OVERHEAD,
  159. "rocksdb.txn.overhead.mutex.old.commit.map"},
  160. {TXN_DUPLICATE_KEY_OVERHEAD, "rocksdb.txn.overhead.duplicate.key"},
  161. {TXN_SNAPSHOT_MUTEX_OVERHEAD, "rocksdb.txn.overhead.mutex.snapshot"},
  162. {TXN_GET_TRY_AGAIN, "rocksdb.txn.get.tryagain"},
  163. {NUMBER_MULTIGET_KEYS_FOUND, "rocksdb.number.multiget.keys.found"},
  164. {NO_ITERATOR_CREATED, "rocksdb.num.iterator.created"},
  165. {NO_ITERATOR_DELETED, "rocksdb.num.iterator.deleted"},
  166. {BLOCK_CACHE_COMPRESSION_DICT_MISS,
  167. "rocksdb.block.cache.compression.dict.miss"},
  168. {BLOCK_CACHE_COMPRESSION_DICT_HIT,
  169. "rocksdb.block.cache.compression.dict.hit"},
  170. {BLOCK_CACHE_COMPRESSION_DICT_ADD,
  171. "rocksdb.block.cache.compression.dict.add"},
  172. {BLOCK_CACHE_COMPRESSION_DICT_BYTES_INSERT,
  173. "rocksdb.block.cache.compression.dict.bytes.insert"},
  174. {BLOCK_CACHE_COMPRESSION_DICT_BYTES_EVICT,
  175. "rocksdb.block.cache.compression.dict.bytes.evict"},
  176. };
  177. const std::vector<std::pair<Histograms, std::string>> HistogramsNameMap = {
  178. {DB_GET, "rocksdb.db.get.micros"},
  179. {DB_WRITE, "rocksdb.db.write.micros"},
  180. {COMPACTION_TIME, "rocksdb.compaction.times.micros"},
  181. {COMPACTION_CPU_TIME, "rocksdb.compaction.times.cpu_micros"},
  182. {SUBCOMPACTION_SETUP_TIME, "rocksdb.subcompaction.setup.times.micros"},
  183. {TABLE_SYNC_MICROS, "rocksdb.table.sync.micros"},
  184. {COMPACTION_OUTFILE_SYNC_MICROS, "rocksdb.compaction.outfile.sync.micros"},
  185. {WAL_FILE_SYNC_MICROS, "rocksdb.wal.file.sync.micros"},
  186. {MANIFEST_FILE_SYNC_MICROS, "rocksdb.manifest.file.sync.micros"},
  187. {TABLE_OPEN_IO_MICROS, "rocksdb.table.open.io.micros"},
  188. {DB_MULTIGET, "rocksdb.db.multiget.micros"},
  189. {READ_BLOCK_COMPACTION_MICROS, "rocksdb.read.block.compaction.micros"},
  190. {READ_BLOCK_GET_MICROS, "rocksdb.read.block.get.micros"},
  191. {WRITE_RAW_BLOCK_MICROS, "rocksdb.write.raw.block.micros"},
  192. {STALL_L0_SLOWDOWN_COUNT, "rocksdb.l0.slowdown.count"},
  193. {STALL_MEMTABLE_COMPACTION_COUNT, "rocksdb.memtable.compaction.count"},
  194. {STALL_L0_NUM_FILES_COUNT, "rocksdb.num.files.stall.count"},
  195. {HARD_RATE_LIMIT_DELAY_COUNT, "rocksdb.hard.rate.limit.delay.count"},
  196. {SOFT_RATE_LIMIT_DELAY_COUNT, "rocksdb.soft.rate.limit.delay.count"},
  197. {NUM_FILES_IN_SINGLE_COMPACTION, "rocksdb.numfiles.in.singlecompaction"},
  198. {DB_SEEK, "rocksdb.db.seek.micros"},
  199. {WRITE_STALL, "rocksdb.db.write.stall"},
  200. {SST_READ_MICROS, "rocksdb.sst.read.micros"},
  201. {NUM_SUBCOMPACTIONS_SCHEDULED, "rocksdb.num.subcompactions.scheduled"},
  202. {BYTES_PER_READ, "rocksdb.bytes.per.read"},
  203. {BYTES_PER_WRITE, "rocksdb.bytes.per.write"},
  204. {BYTES_PER_MULTIGET, "rocksdb.bytes.per.multiget"},
  205. {BYTES_COMPRESSED, "rocksdb.bytes.compressed"},
  206. {BYTES_DECOMPRESSED, "rocksdb.bytes.decompressed"},
  207. {COMPRESSION_TIMES_NANOS, "rocksdb.compression.times.nanos"},
  208. {DECOMPRESSION_TIMES_NANOS, "rocksdb.decompression.times.nanos"},
  209. {READ_NUM_MERGE_OPERANDS, "rocksdb.read.num.merge_operands"},
  210. {BLOB_DB_KEY_SIZE, "rocksdb.blobdb.key.size"},
  211. {BLOB_DB_VALUE_SIZE, "rocksdb.blobdb.value.size"},
  212. {BLOB_DB_WRITE_MICROS, "rocksdb.blobdb.write.micros"},
  213. {BLOB_DB_GET_MICROS, "rocksdb.blobdb.get.micros"},
  214. {BLOB_DB_MULTIGET_MICROS, "rocksdb.blobdb.multiget.micros"},
  215. {BLOB_DB_SEEK_MICROS, "rocksdb.blobdb.seek.micros"},
  216. {BLOB_DB_NEXT_MICROS, "rocksdb.blobdb.next.micros"},
  217. {BLOB_DB_PREV_MICROS, "rocksdb.blobdb.prev.micros"},
  218. {BLOB_DB_BLOB_FILE_WRITE_MICROS, "rocksdb.blobdb.blob.file.write.micros"},
  219. {BLOB_DB_BLOB_FILE_READ_MICROS, "rocksdb.blobdb.blob.file.read.micros"},
  220. {BLOB_DB_BLOB_FILE_SYNC_MICROS, "rocksdb.blobdb.blob.file.sync.micros"},
  221. {BLOB_DB_GC_MICROS, "rocksdb.blobdb.gc.micros"},
  222. {BLOB_DB_COMPRESSION_MICROS, "rocksdb.blobdb.compression.micros"},
  223. {BLOB_DB_DECOMPRESSION_MICROS, "rocksdb.blobdb.decompression.micros"},
  224. {FLUSH_TIME, "rocksdb.db.flush.micros"},
  225. {SST_BATCH_SIZE, "rocksdb.sst.batch.size"},
  226. };
  227. std::shared_ptr<Statistics> CreateDBStatistics() {
  228. return std::make_shared<StatisticsImpl>(nullptr);
  229. }
  230. StatisticsImpl::StatisticsImpl(std::shared_ptr<Statistics> stats)
  231. : stats_(std::move(stats)) {}
  232. StatisticsImpl::~StatisticsImpl() {}
  233. uint64_t StatisticsImpl::getTickerCount(uint32_t tickerType) const {
  234. MutexLock lock(&aggregate_lock_);
  235. return getTickerCountLocked(tickerType);
  236. }
  237. uint64_t StatisticsImpl::getTickerCountLocked(uint32_t tickerType) const {
  238. assert(tickerType < TICKER_ENUM_MAX);
  239. uint64_t res = 0;
  240. for (size_t core_idx = 0; core_idx < per_core_stats_.Size(); ++core_idx) {
  241. res += per_core_stats_.AccessAtCore(core_idx)->tickers_[tickerType];
  242. }
  243. return res;
  244. }
  245. void StatisticsImpl::histogramData(uint32_t histogramType,
  246. HistogramData* const data) const {
  247. MutexLock lock(&aggregate_lock_);
  248. getHistogramImplLocked(histogramType)->Data(data);
  249. }
  250. std::unique_ptr<HistogramImpl> StatisticsImpl::getHistogramImplLocked(
  251. uint32_t histogramType) const {
  252. assert(histogramType < HISTOGRAM_ENUM_MAX);
  253. std::unique_ptr<HistogramImpl> res_hist(new HistogramImpl());
  254. for (size_t core_idx = 0; core_idx < per_core_stats_.Size(); ++core_idx) {
  255. res_hist->Merge(
  256. per_core_stats_.AccessAtCore(core_idx)->histograms_[histogramType]);
  257. }
  258. return res_hist;
  259. }
  260. std::string StatisticsImpl::getHistogramString(uint32_t histogramType) const {
  261. MutexLock lock(&aggregate_lock_);
  262. return getHistogramImplLocked(histogramType)->ToString();
  263. }
  264. void StatisticsImpl::setTickerCount(uint32_t tickerType, uint64_t count) {
  265. {
  266. MutexLock lock(&aggregate_lock_);
  267. setTickerCountLocked(tickerType, count);
  268. }
  269. if (stats_ && tickerType < TICKER_ENUM_MAX) {
  270. stats_->setTickerCount(tickerType, count);
  271. }
  272. }
  273. void StatisticsImpl::setTickerCountLocked(uint32_t tickerType, uint64_t count) {
  274. assert(tickerType < TICKER_ENUM_MAX);
  275. for (size_t core_idx = 0; core_idx < per_core_stats_.Size(); ++core_idx) {
  276. if (core_idx == 0) {
  277. per_core_stats_.AccessAtCore(core_idx)->tickers_[tickerType] = count;
  278. } else {
  279. per_core_stats_.AccessAtCore(core_idx)->tickers_[tickerType] = 0;
  280. }
  281. }
  282. }
  283. uint64_t StatisticsImpl::getAndResetTickerCount(uint32_t tickerType) {
  284. uint64_t sum = 0;
  285. {
  286. MutexLock lock(&aggregate_lock_);
  287. assert(tickerType < TICKER_ENUM_MAX);
  288. for (size_t core_idx = 0; core_idx < per_core_stats_.Size(); ++core_idx) {
  289. sum +=
  290. per_core_stats_.AccessAtCore(core_idx)->tickers_[tickerType].exchange(
  291. 0, std::memory_order_relaxed);
  292. }
  293. }
  294. if (stats_ && tickerType < TICKER_ENUM_MAX) {
  295. stats_->setTickerCount(tickerType, 0);
  296. }
  297. return sum;
  298. }
  299. void StatisticsImpl::recordTick(uint32_t tickerType, uint64_t count) {
  300. assert(tickerType < TICKER_ENUM_MAX);
  301. per_core_stats_.Access()->tickers_[tickerType].fetch_add(
  302. count, std::memory_order_relaxed);
  303. if (stats_ && tickerType < TICKER_ENUM_MAX) {
  304. stats_->recordTick(tickerType, count);
  305. }
  306. }
  307. void StatisticsImpl::recordInHistogram(uint32_t histogramType, uint64_t value) {
  308. assert(histogramType < HISTOGRAM_ENUM_MAX);
  309. if (get_stats_level() <= StatsLevel::kExceptHistogramOrTimers) {
  310. return;
  311. }
  312. per_core_stats_.Access()->histograms_[histogramType].Add(value);
  313. if (stats_ && histogramType < HISTOGRAM_ENUM_MAX) {
  314. stats_->recordInHistogram(histogramType, value);
  315. }
  316. }
  317. Status StatisticsImpl::Reset() {
  318. MutexLock lock(&aggregate_lock_);
  319. for (uint32_t i = 0; i < TICKER_ENUM_MAX; ++i) {
  320. setTickerCountLocked(i, 0);
  321. }
  322. for (uint32_t i = 0; i < HISTOGRAM_ENUM_MAX; ++i) {
  323. for (size_t core_idx = 0; core_idx < per_core_stats_.Size(); ++core_idx) {
  324. per_core_stats_.AccessAtCore(core_idx)->histograms_[i].Clear();
  325. }
  326. }
  327. return Status::OK();
  328. }
  329. namespace {
  330. // a buffer size used for temp string buffers
  331. const int kTmpStrBufferSize = 200;
  332. } // namespace
  333. std::string StatisticsImpl::ToString() const {
  334. MutexLock lock(&aggregate_lock_);
  335. std::string res;
  336. res.reserve(20000);
  337. for (const auto& t : TickersNameMap) {
  338. assert(t.first < TICKER_ENUM_MAX);
  339. char buffer[kTmpStrBufferSize];
  340. snprintf(buffer, kTmpStrBufferSize, "%s COUNT : %" PRIu64 "\n",
  341. t.second.c_str(), getTickerCountLocked(t.first));
  342. res.append(buffer);
  343. }
  344. for (const auto& h : HistogramsNameMap) {
  345. assert(h.first < HISTOGRAM_ENUM_MAX);
  346. char buffer[kTmpStrBufferSize];
  347. HistogramData hData;
  348. getHistogramImplLocked(h.first)->Data(&hData);
  349. // don't handle failures - buffer should always be big enough and arguments
  350. // should be provided correctly
  351. int ret =
  352. snprintf(buffer, kTmpStrBufferSize,
  353. "%s P50 : %f P95 : %f P99 : %f P100 : %f COUNT : %" PRIu64
  354. " SUM : %" PRIu64 "\n",
  355. h.second.c_str(), hData.median, hData.percentile95,
  356. hData.percentile99, hData.max, hData.count, hData.sum);
  357. if (ret < 0 || ret >= kTmpStrBufferSize) {
  358. assert(false);
  359. continue;
  360. }
  361. res.append(buffer);
  362. }
  363. res.shrink_to_fit();
  364. return res;
  365. }
  366. bool StatisticsImpl::getTickerMap(
  367. std::map<std::string, uint64_t>* stats_map) const {
  368. assert(stats_map);
  369. if (!stats_map) return false;
  370. stats_map->clear();
  371. MutexLock lock(&aggregate_lock_);
  372. for (const auto& t : TickersNameMap) {
  373. assert(t.first < TICKER_ENUM_MAX);
  374. (*stats_map)[t.second.c_str()] = getTickerCountLocked(t.first);
  375. }
  376. return true;
  377. }
  378. bool StatisticsImpl::HistEnabledForType(uint32_t type) const {
  379. return type < HISTOGRAM_ENUM_MAX;
  380. }
  381. } // namespace ROCKSDB_NAMESPACE