Improve the design and native object management of Stats in RocksJava

Summary: Closes https://github.com/facebook/rocksdb/pull/2551

Differential Revision: D5399288

Pulled By: sagar0

fbshipit-source-id: dd3df2ed6cc5ae612db0998ea746cc29fccf568e
main
Adam Retter 7 years ago committed by Facebook Github Bot
parent 269d383d5d
commit 000bf0af38
  1. 1
      java/CMakeLists.txt
  2. 15
      java/Makefile
  3. 66
      java/rocksjni/options.cc
  4. 597
      java/rocksjni/portal.h
  5. 220
      java/rocksjni/statistics.cc
  6. 33
      java/rocksjni/statisticsjni.cc
  7. 33
      java/rocksjni/statisticsjni.h
  8. 22
      java/src/main/java/org/rocksdb/DBOptions.java
  9. 13
      java/src/main/java/org/rocksdb/DBOptionsInterface.java
  10. 130
      java/src/main/java/org/rocksdb/HistogramType.java
  11. 2
      java/src/main/java/org/rocksdb/InfoLogLevel.java
  12. 22
      java/src/main/java/org/rocksdb/Options.java
  13. 140
      java/src/main/java/org/rocksdb/Statistics.java
  14. 26
      java/src/main/java/org/rocksdb/StatisticsCollector.java
  15. 65
      java/src/main/java/org/rocksdb/StatsLevel.java
  16. 678
      java/src/main/java/org/rocksdb/TickerType.java
  17. 14
      java/src/test/java/org/rocksdb/DBOptionsTest.java
  18. 17
      java/src/test/java/org/rocksdb/OptionsTest.java
  19. 29
      java/src/test/java/org/rocksdb/StatisticsCollectorTest.java
  20. 160
      java/src/test/java/org/rocksdb/StatisticsTest.java
  21. 1
      src.mk

@ -31,6 +31,7 @@ set(JNI_NATIVE_SOURCES
rocksjni/snapshot.cc
rocksjni/sst_file_writerjni.cc
rocksjni/statistics.cc
rocksjni/statisticsjni.cc
rocksjni/table.cc
rocksjni/transaction_log.cc
rocksjni/ttl.cc

@ -1,5 +1,5 @@
NATIVE_JAVA_CLASSES = org.rocksdb.AbstractCompactionFilter\
org.rocksdb.AbstractComparator\
org.rocksdb.AbstractComparator\
org.rocksdb.AbstractSlice\
org.rocksdb.BackupEngine\
org.rocksdb.BackupableDBOptions\
@ -69,9 +69,9 @@ ROCKSDB_JAR = rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PATCH)-osx.
endif
JAVA_TESTS = org.rocksdb.BackupableDBOptionsTest\
org.rocksdb.BackupEngineTest\
org.rocksdb.BackupEngineTest\
org.rocksdb.BlockBasedTableConfigTest\
org.rocksdb.util.BytewiseComparatorTest\
org.rocksdb.util.BytewiseComparatorTest\
org.rocksdb.CheckPointTest\
org.rocksdb.ClockCacheTest\
org.rocksdb.ColumnFamilyOptionsTest\
@ -94,13 +94,13 @@ JAVA_TESTS = org.rocksdb.BackupableDBOptionsTest\
org.rocksdb.FlushTest\
org.rocksdb.InfoLogLevelTest\
org.rocksdb.KeyMayExistTest\
org.rocksdb.LoggerTest\
org.rocksdb.LoggerTest\
org.rocksdb.LRUCacheTest\
org.rocksdb.MemTableTest\
org.rocksdb.MergeTest\
org.rocksdb.MixedOptionsTest\
org.rocksdb.MutableColumnFamilyOptionsTest\
org.rocksdb.NativeLibraryLoaderTest\
org.rocksdb.MutableColumnFamilyOptionsTest\
org.rocksdb.NativeLibraryLoaderTest\
org.rocksdb.OptionsTest\
org.rocksdb.PlainTableConfigTest\
org.rocksdb.RateLimiterTest\
@ -117,11 +117,12 @@ JAVA_TESTS = org.rocksdb.BackupableDBOptionsTest\
org.rocksdb.SstFileWriterTest\
org.rocksdb.TransactionLogIteratorTest\
org.rocksdb.TtlDBTest\
org.rocksdb.StatisticsTest\
org.rocksdb.StatisticsCollectorTest\
org.rocksdb.WALRecoveryModeTest\
org.rocksdb.WriteBatchHandlerTest\
org.rocksdb.WriteBatchTest\
org.rocksdb.WriteBatchThreadedTest\
org.rocksdb.WriteBatchThreadedTest\
org.rocksdb.WriteOptionsTest\
org.rocksdb.WriteBatchWithIndexTest

@ -21,6 +21,7 @@
#include "rocksjni/comparatorjnicallback.h"
#include "rocksjni/portal.h"
#include "rocksjni/statisticsjni.h"
#include "rocksdb/db.h"
#include "rocksdb/options.h"
@ -224,24 +225,34 @@ void Java_org_rocksdb_Options_setMaxWriteBufferNumber(
/*
* Class: org_rocksdb_Options
* Method: createStatistics
* Signature: (J)V
* Method: setStatistics
* Signature: (JJ)V
*/
void Java_org_rocksdb_Options_createStatistics(
JNIEnv* env, jobject jobj, jlong jOptHandle) {
reinterpret_cast<rocksdb::Options*>(jOptHandle)->statistics =
rocksdb::CreateDBStatistics();
void Java_org_rocksdb_Options_setStatistics(
JNIEnv* env, jobject jobj, jlong jhandle, jlong jstatistics_handle) {
auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle);
auto* pSptr =
reinterpret_cast<std::shared_ptr<rocksdb::StatisticsJni>*>(
jstatistics_handle);
opt->statistics = *pSptr;
}
/*
* Class: org_rocksdb_Options
* Method: statisticsPtr
* Method: statistics
* Signature: (J)J
*/
jlong Java_org_rocksdb_Options_statisticsPtr(
JNIEnv* env, jobject jobj, jlong jOptHandle) {
auto* st = reinterpret_cast<rocksdb::Options*>(jOptHandle)->statistics.get();
return reinterpret_cast<jlong>(st);
jlong Java_org_rocksdb_Options_statistics(
JNIEnv* env, jobject jobj, jlong jhandle) {
auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle);
std::shared_ptr<rocksdb::Statistics> sptr = opt->statistics;
if (sptr == nullptr) {
return 0;
} else {
std::shared_ptr<rocksdb::Statistics>* pSptr =
new std::shared_ptr<rocksdb::Statistics>(sptr);
return reinterpret_cast<jlong>(pSptr);
}
}
/*
@ -4376,25 +4387,34 @@ jint Java_org_rocksdb_DBOptions_maxFileOpeningThreads(
/*
* Class: org_rocksdb_DBOptions
* Method: createStatistics
* Signature: (J)V
* Method: setStatistics
* Signature: (JJ)V
*/
void Java_org_rocksdb_DBOptions_createStatistics(
JNIEnv* env, jobject jobj, jlong jOptHandle) {
reinterpret_cast<rocksdb::DBOptions*>(jOptHandle)->statistics =
rocksdb::CreateDBStatistics();
void Java_org_rocksdb_DBOptions_setStatistics(
JNIEnv* env, jobject jobj, jlong jhandle, jlong jstatistics_handle) {
auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle);
auto* pSptr =
reinterpret_cast<std::shared_ptr<rocksdb::StatisticsJni>*>(
jstatistics_handle);
opt->statistics = *pSptr;
}
/*
* Class: org_rocksdb_DBOptions
* Method: statisticsPtr
* Method: statistics
* Signature: (J)J
*/
jlong Java_org_rocksdb_DBOptions_statisticsPtr(
JNIEnv* env, jobject jobj, jlong jOptHandle) {
auto* st = reinterpret_cast<rocksdb::DBOptions*>(jOptHandle)->
statistics.get();
return reinterpret_cast<jlong>(st);
jlong Java_org_rocksdb_DBOptions_statistics(
JNIEnv* env, jobject jobj, jlong jhandle) {
auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle);
std::shared_ptr<rocksdb::Statistics> sptr = opt->statistics;
if (sptr == nullptr) {
return 0;
} else {
std::shared_ptr<rocksdb::Statistics>* pSptr =
new std::shared_ptr<rocksdb::Statistics>(sptr);
return reinterpret_cast<jlong>(pSptr);
}
}
/*

@ -2283,6 +2283,603 @@ class WALRecoveryModeJni {
}
};
// The portal class for org.rocksdb.TickerType
class TickerTypeJni {
public:
// Returns the equivalent org.rocksdb.TickerType for the provided
// C++ rocksdb::Tickers enum
static jbyte toJavaTickerType(
const rocksdb::Tickers& tickers) {
switch(tickers) {
case rocksdb::Tickers::BLOCK_CACHE_MISS:
return 0x0;
case rocksdb::Tickers::BLOCK_CACHE_HIT:
return 0x1;
case rocksdb::Tickers::BLOCK_CACHE_ADD:
return 0x2;
case rocksdb::Tickers::BLOCK_CACHE_ADD_FAILURES:
return 0x3;
case rocksdb::Tickers::BLOCK_CACHE_INDEX_MISS:
return 0x4;
case rocksdb::Tickers::BLOCK_CACHE_INDEX_HIT:
return 0x5;
case rocksdb::Tickers::BLOCK_CACHE_INDEX_ADD:
return 0x6;
case rocksdb::Tickers::BLOCK_CACHE_INDEX_BYTES_INSERT:
return 0x7;
case rocksdb::Tickers::BLOCK_CACHE_INDEX_BYTES_EVICT:
return 0x8;
case rocksdb::Tickers::BLOCK_CACHE_FILTER_MISS:
return 0x9;
case rocksdb::Tickers::BLOCK_CACHE_FILTER_HIT:
return 0xA;
case rocksdb::Tickers::BLOCK_CACHE_FILTER_ADD:
return 0xB;
case rocksdb::Tickers::BLOCK_CACHE_FILTER_BYTES_INSERT:
return 0xC;
case rocksdb::Tickers::BLOCK_CACHE_FILTER_BYTES_EVICT:
return 0xD;
case rocksdb::Tickers::BLOCK_CACHE_DATA_MISS:
return 0xE;
case rocksdb::Tickers::BLOCK_CACHE_DATA_HIT:
return 0xF;
case rocksdb::Tickers::BLOCK_CACHE_DATA_ADD:
return 0x10;
case rocksdb::Tickers::BLOCK_CACHE_DATA_BYTES_INSERT:
return 0x11;
case rocksdb::Tickers::BLOCK_CACHE_BYTES_READ:
return 0x12;
case rocksdb::Tickers::BLOCK_CACHE_BYTES_WRITE:
return 0x13;
case rocksdb::Tickers::BLOOM_FILTER_USEFUL:
return 0x14;
case rocksdb::Tickers::PERSISTENT_CACHE_HIT:
return 0x15;
case rocksdb::Tickers::PERSISTENT_CACHE_MISS:
return 0x16;
case rocksdb::Tickers::SIM_BLOCK_CACHE_HIT:
return 0x17;
case rocksdb::Tickers::SIM_BLOCK_CACHE_MISS:
return 0x18;
case rocksdb::Tickers::MEMTABLE_HIT:
return 0x19;
case rocksdb::Tickers::MEMTABLE_MISS:
return 0x1A;
case rocksdb::Tickers::GET_HIT_L0:
return 0x1B;
case rocksdb::Tickers::GET_HIT_L1:
return 0x1C;
case rocksdb::Tickers::GET_HIT_L2_AND_UP:
return 0x1D;
case rocksdb::Tickers::COMPACTION_KEY_DROP_NEWER_ENTRY:
return 0x1E;
case rocksdb::Tickers::COMPACTION_KEY_DROP_OBSOLETE:
return 0x1F;
case rocksdb::Tickers::COMPACTION_KEY_DROP_RANGE_DEL:
return 0x20;
case rocksdb::Tickers::COMPACTION_KEY_DROP_USER:
return 0x21;
case rocksdb::Tickers::COMPACTION_RANGE_DEL_DROP_OBSOLETE:
return 0x22;
case rocksdb::Tickers::NUMBER_KEYS_WRITTEN:
return 0x23;
case rocksdb::Tickers::NUMBER_KEYS_READ:
return 0x24;
case rocksdb::Tickers::NUMBER_KEYS_UPDATED:
return 0x25;
case rocksdb::Tickers::BYTES_WRITTEN:
return 0x26;
case rocksdb::Tickers::BYTES_READ:
return 0x27;
case rocksdb::Tickers::NUMBER_DB_SEEK:
return 0x28;
case rocksdb::Tickers::NUMBER_DB_NEXT:
return 0x29;
case rocksdb::Tickers::NUMBER_DB_PREV:
return 0x2A;
case rocksdb::Tickers::NUMBER_DB_SEEK_FOUND:
return 0x2B;
case rocksdb::Tickers::NUMBER_DB_NEXT_FOUND:
return 0x2C;
case rocksdb::Tickers::NUMBER_DB_PREV_FOUND:
return 0x2D;
case rocksdb::Tickers::ITER_BYTES_READ:
return 0x2E;
case rocksdb::Tickers::NO_FILE_CLOSES:
return 0x2F;
case rocksdb::Tickers::NO_FILE_OPENS:
return 0x30;
case rocksdb::Tickers::NO_FILE_ERRORS:
return 0x31;
case rocksdb::Tickers::STALL_L0_SLOWDOWN_MICROS:
return 0x32;
case rocksdb::Tickers::STALL_MEMTABLE_COMPACTION_MICROS:
return 0x33;
case rocksdb::Tickers::STALL_L0_NUM_FILES_MICROS:
return 0x34;
case rocksdb::Tickers::STALL_MICROS:
return 0x35;
case rocksdb::Tickers::DB_MUTEX_WAIT_MICROS:
return 0x36;
case rocksdb::Tickers::RATE_LIMIT_DELAY_MILLIS:
return 0x37;
case rocksdb::Tickers::NO_ITERATORS:
return 0x38;
case rocksdb::Tickers::NUMBER_MULTIGET_CALLS:
return 0x39;
case rocksdb::Tickers::NUMBER_MULTIGET_KEYS_READ:
return 0x3A;
case rocksdb::Tickers::NUMBER_MULTIGET_BYTES_READ:
return 0x3B;
case rocksdb::Tickers::NUMBER_FILTERED_DELETES:
return 0x3C;
case rocksdb::Tickers::NUMBER_MERGE_FAILURES:
return 0x3D;
case rocksdb::Tickers::BLOOM_FILTER_PREFIX_CHECKED:
return 0x3E;
case rocksdb::Tickers::BLOOM_FILTER_PREFIX_USEFUL:
return 0x3F;
case rocksdb::Tickers::NUMBER_OF_RESEEKS_IN_ITERATION:
return 0x40;
case rocksdb::Tickers::GET_UPDATES_SINCE_CALLS:
return 0x41;
case rocksdb::Tickers::BLOCK_CACHE_COMPRESSED_MISS:
return 0x42;
case rocksdb::Tickers::BLOCK_CACHE_COMPRESSED_HIT:
return 0x43;
case rocksdb::Tickers::BLOCK_CACHE_COMPRESSED_ADD:
return 0x44;
case rocksdb::Tickers::BLOCK_CACHE_COMPRESSED_ADD_FAILURES:
return 0x45;
case rocksdb::Tickers::WAL_FILE_SYNCED:
return 0x46;
case rocksdb::Tickers::WAL_FILE_BYTES:
return 0x47;
case rocksdb::Tickers::WRITE_DONE_BY_SELF:
return 0x48;
case rocksdb::Tickers::WRITE_DONE_BY_OTHER:
return 0x49;
case rocksdb::Tickers::WRITE_TIMEDOUT:
return 0x4A;
case rocksdb::Tickers::WRITE_WITH_WAL:
return 0x4B;
case rocksdb::Tickers::COMPACT_READ_BYTES:
return 0x4C;
case rocksdb::Tickers::COMPACT_WRITE_BYTES:
return 0x4D;
case rocksdb::Tickers::FLUSH_WRITE_BYTES:
return 0x4E;
case rocksdb::Tickers::NUMBER_DIRECT_LOAD_TABLE_PROPERTIES:
return 0x4F;
case rocksdb::Tickers::NUMBER_SUPERVERSION_ACQUIRES:
return 0x50;
case rocksdb::Tickers::NUMBER_SUPERVERSION_RELEASES:
return 0x51;
case rocksdb::Tickers::NUMBER_SUPERVERSION_CLEANUPS:
return 0x52;
case rocksdb::Tickers::NUMBER_BLOCK_COMPRESSED:
return 0x53;
case rocksdb::Tickers::NUMBER_BLOCK_DECOMPRESSED:
return 0x54;
case rocksdb::Tickers::NUMBER_BLOCK_NOT_COMPRESSED:
return 0x55;
case rocksdb::Tickers::MERGE_OPERATION_TOTAL_TIME:
return 0x56;
case rocksdb::Tickers::FILTER_OPERATION_TOTAL_TIME:
return 0x57;
case rocksdb::Tickers::ROW_CACHE_HIT:
return 0x58;
case rocksdb::Tickers::ROW_CACHE_MISS:
return 0x59;
case rocksdb::Tickers::READ_AMP_ESTIMATE_USEFUL_BYTES:
return 0x5A;
case rocksdb::Tickers::READ_AMP_TOTAL_READ_BYTES:
return 0x5B;
case rocksdb::Tickers::NUMBER_RATE_LIMITER_DRAINS:
return 0x5C;
case rocksdb::Tickers::TICKER_ENUM_MAX:
return 0x5D;
default:
// undefined/default
return 0x0;
}
}
// Returns the equivalent C++ rocksdb::Tickers enum for the
// provided Java org.rocksdb.TickerType
static rocksdb::Tickers toCppTickers(jbyte jticker_type) {
switch(jticker_type) {
case 0x0:
return rocksdb::Tickers::BLOCK_CACHE_MISS;
case 0x1:
return rocksdb::Tickers::BLOCK_CACHE_HIT;
case 0x2:
return rocksdb::Tickers::BLOCK_CACHE_ADD;
case 0x3:
return rocksdb::Tickers::BLOCK_CACHE_ADD_FAILURES;
case 0x4:
return rocksdb::Tickers::BLOCK_CACHE_INDEX_MISS;
case 0x5:
return rocksdb::Tickers::BLOCK_CACHE_INDEX_HIT;
case 0x6:
return rocksdb::Tickers::BLOCK_CACHE_INDEX_ADD;
case 0x7:
return rocksdb::Tickers::BLOCK_CACHE_INDEX_BYTES_INSERT;
case 0x8:
return rocksdb::Tickers::BLOCK_CACHE_INDEX_BYTES_EVICT;
case 0x9:
return rocksdb::Tickers::BLOCK_CACHE_FILTER_MISS;
case 0xA:
return rocksdb::Tickers::BLOCK_CACHE_FILTER_HIT;
case 0xB:
return rocksdb::Tickers::BLOCK_CACHE_FILTER_ADD;
case 0xC:
return rocksdb::Tickers::BLOCK_CACHE_FILTER_BYTES_INSERT;
case 0xD:
return rocksdb::Tickers::BLOCK_CACHE_FILTER_BYTES_EVICT;
case 0xE:
return rocksdb::Tickers::BLOCK_CACHE_DATA_MISS;
case 0xF:
return rocksdb::Tickers::BLOCK_CACHE_DATA_HIT;
case 0x10:
return rocksdb::Tickers::BLOCK_CACHE_DATA_ADD;
case 0x11:
return rocksdb::Tickers::BLOCK_CACHE_DATA_BYTES_INSERT;
case 0x12:
return rocksdb::Tickers::BLOCK_CACHE_BYTES_READ;
case 0x13:
return rocksdb::Tickers::BLOCK_CACHE_BYTES_WRITE;
case 0x14:
return rocksdb::Tickers::BLOOM_FILTER_USEFUL;
case 0x15:
return rocksdb::Tickers::PERSISTENT_CACHE_HIT;
case 0x16:
return rocksdb::Tickers::PERSISTENT_CACHE_MISS;
case 0x17:
return rocksdb::Tickers::SIM_BLOCK_CACHE_HIT;
case 0x18:
return rocksdb::Tickers::SIM_BLOCK_CACHE_MISS;
case 0x19:
return rocksdb::Tickers::MEMTABLE_HIT;
case 0x1A:
return rocksdb::Tickers::MEMTABLE_MISS;
case 0x1B:
return rocksdb::Tickers::GET_HIT_L0;
case 0x1C:
return rocksdb::Tickers::GET_HIT_L1;
case 0x1D:
return rocksdb::Tickers::GET_HIT_L2_AND_UP;
case 0x1E:
return rocksdb::Tickers::COMPACTION_KEY_DROP_NEWER_ENTRY;
case 0x1F:
return rocksdb::Tickers::COMPACTION_KEY_DROP_OBSOLETE;
case 0x20:
return rocksdb::Tickers::COMPACTION_KEY_DROP_RANGE_DEL;
case 0x21:
return rocksdb::Tickers::COMPACTION_KEY_DROP_USER;
case 0x22:
return rocksdb::Tickers::COMPACTION_RANGE_DEL_DROP_OBSOLETE;
case 0x23:
return rocksdb::Tickers::NUMBER_KEYS_WRITTEN;
case 0x24:
return rocksdb::Tickers::NUMBER_KEYS_READ;
case 0x25:
return rocksdb::Tickers::NUMBER_KEYS_UPDATED;
case 0x26:
return rocksdb::Tickers::BYTES_WRITTEN;
case 0x27:
return rocksdb::Tickers::BYTES_READ;
case 0x28:
return rocksdb::Tickers::NUMBER_DB_SEEK;
case 0x29:
return rocksdb::Tickers::NUMBER_DB_NEXT;
case 0x2A:
return rocksdb::Tickers::NUMBER_DB_PREV;
case 0x2B:
return rocksdb::Tickers::NUMBER_DB_SEEK_FOUND;
case 0x2C:
return rocksdb::Tickers::NUMBER_DB_NEXT_FOUND;
case 0x2D:
return rocksdb::Tickers::NUMBER_DB_PREV_FOUND;
case 0x2E:
return rocksdb::Tickers::ITER_BYTES_READ;
case 0x2F:
return rocksdb::Tickers::NO_FILE_CLOSES;
case 0x30:
return rocksdb::Tickers::NO_FILE_OPENS;
case 0x31:
return rocksdb::Tickers::NO_FILE_ERRORS;
case 0x32:
return rocksdb::Tickers::STALL_L0_SLOWDOWN_MICROS;
case 0x33:
return rocksdb::Tickers::STALL_MEMTABLE_COMPACTION_MICROS;
case 0x34:
return rocksdb::Tickers::STALL_L0_NUM_FILES_MICROS;
case 0x35:
return rocksdb::Tickers::STALL_MICROS;
case 0x36:
return rocksdb::Tickers::DB_MUTEX_WAIT_MICROS;
case 0x37:
return rocksdb::Tickers::RATE_LIMIT_DELAY_MILLIS;
case 0x38:
return rocksdb::Tickers::NO_ITERATORS;
case 0x39:
return rocksdb::Tickers::NUMBER_MULTIGET_CALLS;
case 0x3A:
return rocksdb::Tickers::NUMBER_MULTIGET_KEYS_READ;
case 0x3B:
return rocksdb::Tickers::NUMBER_MULTIGET_BYTES_READ;
case 0x3C:
return rocksdb::Tickers::NUMBER_FILTERED_DELETES;
case 0x3D:
return rocksdb::Tickers::NUMBER_MERGE_FAILURES;
case 0x3E:
return rocksdb::Tickers::BLOOM_FILTER_PREFIX_CHECKED;
case 0x3F:
return rocksdb::Tickers::BLOOM_FILTER_PREFIX_USEFUL;
case 0x40:
return rocksdb::Tickers::NUMBER_OF_RESEEKS_IN_ITERATION;
case 0x41:
return rocksdb::Tickers::GET_UPDATES_SINCE_CALLS;
case 0x42:
return rocksdb::Tickers::BLOCK_CACHE_COMPRESSED_MISS;
case 0x43:
return rocksdb::Tickers::BLOCK_CACHE_COMPRESSED_HIT;
case 0x44:
return rocksdb::Tickers::BLOCK_CACHE_COMPRESSED_ADD;
case 0x45:
return rocksdb::Tickers::BLOCK_CACHE_COMPRESSED_ADD_FAILURES;
case 0x46:
return rocksdb::Tickers::WAL_FILE_SYNCED;
case 0x47:
return rocksdb::Tickers::WAL_FILE_BYTES;
case 0x48:
return rocksdb::Tickers::WRITE_DONE_BY_SELF;
case 0x49:
return rocksdb::Tickers::WRITE_DONE_BY_OTHER;
case 0x4A:
return rocksdb::Tickers::WRITE_TIMEDOUT;
case 0x4B:
return rocksdb::Tickers::WRITE_WITH_WAL;
case 0x4C:
return rocksdb::Tickers::COMPACT_READ_BYTES;
case 0x4D:
return rocksdb::Tickers::COMPACT_WRITE_BYTES;
case 0x4E:
return rocksdb::Tickers::FLUSH_WRITE_BYTES;
case 0x4F:
return rocksdb::Tickers::NUMBER_DIRECT_LOAD_TABLE_PROPERTIES;
case 0x50:
return rocksdb::Tickers::NUMBER_SUPERVERSION_ACQUIRES;
case 0x51:
return rocksdb::Tickers::NUMBER_SUPERVERSION_RELEASES;
case 0x52:
return rocksdb::Tickers::NUMBER_SUPERVERSION_CLEANUPS;
case 0x53:
return rocksdb::Tickers::NUMBER_BLOCK_COMPRESSED;
case 0x54:
return rocksdb::Tickers::NUMBER_BLOCK_DECOMPRESSED;
case 0x55:
return rocksdb::Tickers::NUMBER_BLOCK_NOT_COMPRESSED;
case 0x56:
return rocksdb::Tickers::MERGE_OPERATION_TOTAL_TIME;
case 0x57:
return rocksdb::Tickers::FILTER_OPERATION_TOTAL_TIME;
case 0x58:
return rocksdb::Tickers::ROW_CACHE_HIT;
case 0x59:
return rocksdb::Tickers::ROW_CACHE_MISS;
case 0x5A:
return rocksdb::Tickers::READ_AMP_ESTIMATE_USEFUL_BYTES;
case 0x5B:
return rocksdb::Tickers::READ_AMP_TOTAL_READ_BYTES;
case 0x5C:
return rocksdb::Tickers::NUMBER_RATE_LIMITER_DRAINS;
case 0x5D:
return rocksdb::Tickers::TICKER_ENUM_MAX;
default:
// undefined/default
return rocksdb::Tickers::BLOCK_CACHE_MISS;
}
}
};
// The portal class for org.rocksdb.HistogramType
class HistogramTypeJni {
public:
// Returns the equivalent org.rocksdb.HistogramType for the provided
// C++ rocksdb::Histograms enum
static jbyte toJavaHistogramsType(
const rocksdb::Histograms& histograms) {
switch(histograms) {
case rocksdb::Histograms::DB_GET:
return 0x0;
case rocksdb::Histograms::DB_WRITE:
return 0x1;
case rocksdb::Histograms::COMPACTION_TIME:
return 0x2;
case rocksdb::Histograms::SUBCOMPACTION_SETUP_TIME:
return 0x3;
case rocksdb::Histograms::TABLE_SYNC_MICROS:
return 0x4;
case rocksdb::Histograms::COMPACTION_OUTFILE_SYNC_MICROS:
return 0x5;
case rocksdb::Histograms::WAL_FILE_SYNC_MICROS:
return 0x6;
case rocksdb::Histograms::MANIFEST_FILE_SYNC_MICROS:
return 0x7;
case rocksdb::Histograms::TABLE_OPEN_IO_MICROS:
return 0x8;
case rocksdb::Histograms::DB_MULTIGET:
return 0x9;
case rocksdb::Histograms::READ_BLOCK_COMPACTION_MICROS:
return 0xA;
case rocksdb::Histograms::READ_BLOCK_GET_MICROS:
return 0xB;
case rocksdb::Histograms::WRITE_RAW_BLOCK_MICROS:
return 0xC;
case rocksdb::Histograms::STALL_L0_SLOWDOWN_COUNT:
return 0xD;
case rocksdb::Histograms::STALL_MEMTABLE_COMPACTION_COUNT:
return 0xE;
case rocksdb::Histograms::STALL_L0_NUM_FILES_COUNT:
return 0xF;
case rocksdb::Histograms::HARD_RATE_LIMIT_DELAY_COUNT:
return 0x10;
case rocksdb::Histograms::SOFT_RATE_LIMIT_DELAY_COUNT:
return 0x11;
case rocksdb::Histograms::NUM_FILES_IN_SINGLE_COMPACTION:
return 0x12;
case rocksdb::Histograms::DB_SEEK:
return 0x13;
case rocksdb::Histograms::WRITE_STALL:
return 0x14;
case rocksdb::Histograms::SST_READ_MICROS:
return 0x15;
case rocksdb::Histograms::NUM_SUBCOMPACTIONS_SCHEDULED:
return 0x16;
case rocksdb::Histograms::BYTES_PER_READ:
return 0x17;
case rocksdb::Histograms::BYTES_PER_WRITE:
return 0x18;
case rocksdb::Histograms::BYTES_PER_MULTIGET:
return 0x19;
case rocksdb::Histograms::BYTES_COMPRESSED:
return 0x1A;
case rocksdb::Histograms::BYTES_DECOMPRESSED:
return 0x1B;
case rocksdb::Histograms::COMPRESSION_TIMES_NANOS:
return 0x1C;
case rocksdb::Histograms::DECOMPRESSION_TIMES_NANOS:
return 0x1D;
case rocksdb::Histograms::READ_NUM_MERGE_OPERANDS:
return 0x1E;
case rocksdb::Histograms::HISTOGRAM_ENUM_MAX:
return 0x1F;
default:
// undefined/default
return 0x0;
}
}
// Returns the equivalent C++ rocksdb::Histograms enum for the
// provided Java org.rocksdb.HistogramsType
static rocksdb::Histograms toCppHistograms(jbyte jhistograms_type) {
switch(jhistograms_type) {
case 0x0:
return rocksdb::Histograms::DB_GET;
case 0x1:
return rocksdb::Histograms::DB_WRITE;
case 0x2:
return rocksdb::Histograms::COMPACTION_TIME;
case 0x3:
return rocksdb::Histograms::SUBCOMPACTION_SETUP_TIME;
case 0x4:
return rocksdb::Histograms::TABLE_SYNC_MICROS;
case 0x5:
return rocksdb::Histograms::COMPACTION_OUTFILE_SYNC_MICROS;
case 0x6:
return rocksdb::Histograms::WAL_FILE_SYNC_MICROS;
case 0x7:
return rocksdb::Histograms::MANIFEST_FILE_SYNC_MICROS;
case 0x8:
return rocksdb::Histograms::TABLE_OPEN_IO_MICROS;
case 0x9:
return rocksdb::Histograms::DB_MULTIGET;
case 0xA:
return rocksdb::Histograms::READ_BLOCK_COMPACTION_MICROS;
case 0xB:
return rocksdb::Histograms::READ_BLOCK_GET_MICROS;
case 0xC:
return rocksdb::Histograms::WRITE_RAW_BLOCK_MICROS;
case 0xD:
return rocksdb::Histograms::STALL_L0_SLOWDOWN_COUNT;
case 0xE:
return rocksdb::Histograms::STALL_MEMTABLE_COMPACTION_COUNT;
case 0xF:
return rocksdb::Histograms::STALL_L0_NUM_FILES_COUNT;
case 0x10:
return rocksdb::Histograms::HARD_RATE_LIMIT_DELAY_COUNT;
case 0x11:
return rocksdb::Histograms::SOFT_RATE_LIMIT_DELAY_COUNT;
case 0x12:
return rocksdb::Histograms::NUM_FILES_IN_SINGLE_COMPACTION;
case 0x13:
return rocksdb::Histograms::DB_SEEK;
case 0x14:
return rocksdb::Histograms::WRITE_STALL;
case 0x15:
return rocksdb::Histograms::SST_READ_MICROS;
case 0x16:
return rocksdb::Histograms::NUM_SUBCOMPACTIONS_SCHEDULED;
case 0x17:
return rocksdb::Histograms::BYTES_PER_READ;
case 0x18:
return rocksdb::Histograms::BYTES_PER_WRITE;
case 0x19:
return rocksdb::Histograms::BYTES_PER_MULTIGET;
case 0x1A:
return rocksdb::Histograms::BYTES_COMPRESSED;
case 0x1B:
return rocksdb::Histograms::BYTES_DECOMPRESSED;
case 0x1C:
return rocksdb::Histograms::COMPRESSION_TIMES_NANOS;
case 0x1D:
return rocksdb::Histograms::DECOMPRESSION_TIMES_NANOS;
case 0x1E:
return rocksdb::Histograms::READ_NUM_MERGE_OPERANDS;
case 0x1F:
return rocksdb::Histograms::HISTOGRAM_ENUM_MAX;
default:
// undefined/default
return rocksdb::Histograms::DB_GET;
}
}
};
// The portal class for org.rocksdb.StatsLevel
class StatsLevelJni {
public:
// Returns the equivalent org.rocksdb.StatsLevel for the provided
// C++ rocksdb::StatsLevel enum
static jbyte toJavaStatsLevel(
const rocksdb::StatsLevel& stats_level) {
switch(stats_level) {
case rocksdb::StatsLevel::kExceptDetailedTimers:
return 0x0;
case rocksdb::StatsLevel::kExceptTimeForMutex:
return 0x1;
case rocksdb::StatsLevel::kAll:
return 0x2;
default:
// undefined/default
return 0x0;
}
}
// Returns the equivalent C++ rocksdb::StatsLevel enum for the
// provided Java org.rocksdb.StatsLevel
static rocksdb::StatsLevel toCppStatsLevel(jbyte jstats_level) {
switch(jstats_level) {
case 0x0:
return rocksdb::StatsLevel::kExceptDetailedTimers;
case 0x1:
return rocksdb::StatsLevel::kExceptTimeForMutex;
case 0x2:
return rocksdb::StatsLevel::kAll;
default:
// undefined/default
return rocksdb::StatsLevel::kExceptDetailedTimers;
}
}
};
// various utility functions for working with RocksDB and JNI
class JniUtil {
public:

@ -6,39 +6,178 @@
// This file implements the "bridge" between Java and C++ and enables
// calling c++ rocksdb::Statistics methods from Java side.
#include <stdio.h>
#include <stdlib.h>
#include <jni.h>
#include <memory>
#include <set>
#include "include/org_rocksdb_Statistics.h"
#include "rocksjni/portal.h"
#include "rocksjni/statisticsjni.h"
#include "rocksdb/statistics.h"
/*
* Class: org_rocksdb_Statistics
* Method: getTickerCount0
* Signature: (IJ)J
* Method: newStatistics
* Signature: ()J
*/
jlong Java_org_rocksdb_Statistics_getTickerCount0(
JNIEnv* env, jobject jobj, jint tickerType, jlong handle) {
auto* st = reinterpret_cast<rocksdb::Statistics*>(handle);
assert(st != nullptr);
return st->getTickerCount(static_cast<rocksdb::Tickers>(tickerType));
jlong Java_org_rocksdb_Statistics_newStatistics__(JNIEnv* env, jclass jcls) {
return Java_org_rocksdb_Statistics_newStatistics___3BJ(
env, jcls, nullptr, 0);
}
/*
* Class: org_rocksdb_Statistics
* Method: getHistogramData0
* Signature: (IJ)Lorg/rocksdb/HistogramData;
* Method: newStatistics
* Signature: (J)J
*/
jobject Java_org_rocksdb_Statistics_getHistogramData0(
JNIEnv* env, jobject jobj, jint histogramType, jlong handle) {
auto* st = reinterpret_cast<rocksdb::Statistics*>(handle);
assert(st != nullptr);
jlong Java_org_rocksdb_Statistics_newStatistics__J(
JNIEnv* env, jclass jcls, jlong jother_statistics_handle) {
return Java_org_rocksdb_Statistics_newStatistics___3BJ(
env, jcls, nullptr, jother_statistics_handle);
}
/*
* Class: org_rocksdb_Statistics
* Method: newStatistics
* Signature: ([B)J
*/
jlong Java_org_rocksdb_Statistics_newStatistics___3B(
JNIEnv* env, jclass jcls, jbyteArray jhistograms) {
return Java_org_rocksdb_Statistics_newStatistics___3BJ(
env, jcls, jhistograms, 0);
}
/*
* Class: org_rocksdb_Statistics
* Method: newStatistics
* Signature: ([BJ)J
*/
jlong Java_org_rocksdb_Statistics_newStatistics___3BJ(
JNIEnv* env, jclass jcls, jbyteArray jhistograms,
jlong jother_statistics_handle) {
std::shared_ptr<rocksdb::Statistics>* pSptr_other_statistics = nullptr;
if (jother_statistics_handle > 0) {
pSptr_other_statistics =
reinterpret_cast<std::shared_ptr<rocksdb::Statistics>*>(
jother_statistics_handle);
}
std::set<uint32_t> histograms;
if (jhistograms != nullptr) {
const jsize len = env->GetArrayLength(jhistograms);
if (len > 0) {
jbyte* jhistogram = env->GetByteArrayElements(jhistograms, nullptr);
if (jhistogram == nullptr ) {
// exception thrown: OutOfMemoryError
return 0;
}
for (jsize i = 0; i < len; i++) {
const rocksdb::Histograms histogram =
rocksdb::HistogramTypeJni::toCppHistograms(jhistogram[i]);
histograms.emplace(histogram);
}
env->ReleaseByteArrayElements(jhistograms, jhistogram, JNI_ABORT);
}
}
std::shared_ptr<rocksdb::Statistics> sptr_other_statistics = nullptr;
if (pSptr_other_statistics != nullptr) {
sptr_other_statistics = *pSptr_other_statistics;
}
auto* pSptr_statistics = new std::shared_ptr<rocksdb::StatisticsJni>(
new rocksdb::StatisticsJni(sptr_other_statistics, histograms));
rocksdb::HistogramData data;
st->histogramData(static_cast<rocksdb::Histograms>(histogramType),
&data);
return reinterpret_cast<jlong>(pSptr_statistics);
}
/*
* Class: org_rocksdb_Statistics
* Method: disposeInternal
* Signature: (J)V
*/
void Java_org_rocksdb_Statistics_disposeInternal(
JNIEnv* env, jobject jobj, jlong jhandle) {
if(jhandle > 0) {
auto* pSptr_statistics =
reinterpret_cast<std::shared_ptr<rocksdb::Statistics>*>(jhandle);
delete pSptr_statistics;
}
}
/*
* Class: org_rocksdb_Statistics
* Method: statsLevel
* Signature: (J)B
*/
jbyte Java_org_rocksdb_Statistics_statsLevel(
JNIEnv* env, jobject jobj, jlong jhandle) {
auto* pSptr_statistics =
reinterpret_cast<std::shared_ptr<rocksdb::Statistics>*>(jhandle);
assert(pSptr_statistics != nullptr);
return rocksdb::StatsLevelJni::toJavaStatsLevel(pSptr_statistics->get()->stats_level_);
}
/*
* Class: org_rocksdb_Statistics
* Method: setStatsLevel
* Signature: (JB)V
*/
void Java_org_rocksdb_Statistics_setStatsLevel(
JNIEnv* env, jobject jobj, jlong jhandle, jbyte jstats_level) {
auto* pSptr_statistics =
reinterpret_cast<std::shared_ptr<rocksdb::Statistics>*>(jhandle);
assert(pSptr_statistics != nullptr);
auto stats_level = rocksdb::StatsLevelJni::toCppStatsLevel(jstats_level);
pSptr_statistics->get()->stats_level_ = stats_level;
}
/*
* Class: org_rocksdb_Statistics
* Method: getTickerCount
* Signature: (JB)J
*/
jlong Java_org_rocksdb_Statistics_getTickerCount(
JNIEnv* env, jobject jobj, jlong jhandle, jbyte jticker_type) {
auto* pSptr_statistics =
reinterpret_cast<std::shared_ptr<rocksdb::Statistics>*>(jhandle);
assert(pSptr_statistics != nullptr);
auto ticker = rocksdb::TickerTypeJni::toCppTickers(jticker_type);
return pSptr_statistics->get()->getTickerCount(ticker);
}
/*
* Class: org_rocksdb_Statistics
* Method: getAndResetTickerCount
* Signature: (JB)J
*/
jlong Java_org_rocksdb_Statistics_getAndResetTickerCount(
JNIEnv* env, jobject jobj, jlong jhandle, jbyte jticker_type) {
auto* pSptr_statistics =
reinterpret_cast<std::shared_ptr<rocksdb::Statistics>*>(jhandle);
assert(pSptr_statistics != nullptr);
auto ticker = rocksdb::TickerTypeJni::toCppTickers(jticker_type);
return pSptr_statistics->get()->getAndResetTickerCount(ticker);
}
/*
* Class: org_rocksdb_Statistics
* Method: getHistogramData
* Signature: (JB)Lorg/rocksdb/HistogramData;
*/
jobject Java_org_rocksdb_Statistics_getHistogramData(
JNIEnv* env, jobject jobj, jlong jhandle, jbyte jhistogram_type) {
auto* pSptr_statistics =
reinterpret_cast<std::shared_ptr<rocksdb::Statistics>*>(jhandle);
assert(pSptr_statistics != nullptr);
rocksdb::HistogramData data; // TODO(AR) perhaps better to construct a Java Object Wrapper that uses ptr to C++ `new HistogramData`
auto histogram = rocksdb::HistogramTypeJni::toCppHistograms(jhistogram_type);
pSptr_statistics->get()->histogramData(
static_cast<rocksdb::Histograms>(histogram), &data);
jclass jclazz = rocksdb::HistogramDataJni::getJClass(env);
if(jclazz == nullptr) {
@ -58,3 +197,48 @@ jobject Java_org_rocksdb_Statistics_getHistogramData0(
mid, data.median, data.percentile95,data.percentile99, data.average,
data.standard_deviation);
}
/*
* Class: org_rocksdb_Statistics
* Method: getHistogramString
* Signature: (JB)Ljava/lang/String;
*/
jstring Java_org_rocksdb_Statistics_getHistogramString(
JNIEnv* env, jobject jobj, jlong jhandle, jbyte jhistogram_type) {
auto* pSptr_statistics =
reinterpret_cast<std::shared_ptr<rocksdb::Statistics>*>(jhandle);
assert(pSptr_statistics != nullptr);
auto histogram = rocksdb::HistogramTypeJni::toCppHistograms(jhistogram_type);
auto str = pSptr_statistics->get()->getHistogramString(histogram);
return env->NewStringUTF(str.c_str());
}
/*
* Class: org_rocksdb_Statistics
* Method: reset
* Signature: (J)V
*/
void Java_org_rocksdb_Statistics_reset(
JNIEnv* env, jobject jobj, jlong jhandle) {
auto* pSptr_statistics =
reinterpret_cast<std::shared_ptr<rocksdb::Statistics>*>(jhandle);
assert(pSptr_statistics != nullptr);
rocksdb::Status s = pSptr_statistics->get()->Reset();
if (!s.ok()) {
rocksdb::RocksDBExceptionJni::ThrowNew(env, s);
}
}
/*
* Class: org_rocksdb_Statistics
* Method: toString
* Signature: (J)Ljava/lang/String;
*/
jstring Java_org_rocksdb_Statistics_toString(
JNIEnv* env, jobject jobj, jlong jhandle) {
auto* pSptr_statistics =
reinterpret_cast<std::shared_ptr<rocksdb::Statistics>*>(jhandle);
assert(pSptr_statistics != nullptr);
auto str = pSptr_statistics->get()->ToString();
return env->NewStringUTF(str.c_str());
}

@ -0,0 +1,33 @@
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
// This file implements the callback "bridge" between Java and C++ for
// rocksdb::Statistics
#include "rocksjni/statisticsjni.h"
namespace rocksdb {
StatisticsJni::StatisticsJni(std::shared_ptr<Statistics> stats)
: StatisticsImpl(stats, false), m_ignore_histograms() {
}
StatisticsJni::StatisticsJni(std::shared_ptr<Statistics> stats,
const std::set<uint32_t> ignore_histograms) : StatisticsImpl(stats, false),
m_ignore_histograms(ignore_histograms) {
}
bool StatisticsJni::HistEnabledForType(uint32_t type) const {
if (type >= HISTOGRAM_ENUM_MAX) {
return false;
}
if (m_ignore_histograms.count(type) > 0) {
return false;
}
return true;
}
};

@ -0,0 +1,33 @@
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
// This file implements the callback "bridge" between Java and C++ for
// rocksdb::Statistics
#ifndef JAVA_ROCKSJNI_STATISTICSJNI_H_
#define JAVA_ROCKSJNI_STATISTICSJNI_H_
#include <memory>
#include <set>
#include <string>
#include "rocksdb/statistics.h"
#include "monitoring/statistics.h"
namespace rocksdb {
class StatisticsJni : public StatisticsImpl {
public:
StatisticsJni(std::shared_ptr<Statistics> stats);
StatisticsJni(std::shared_ptr<Statistics> stats,
const std::set<uint32_t> ignore_histograms);
virtual bool HistEnabledForType(uint32_t type) const override;
private:
const std::set<uint32_t> m_ignore_histograms;
};
} // namespace rocksdb
#endif // JAVA_ROCKSJNI_STATISTICSJNI_H_

@ -226,23 +226,21 @@ public class DBOptions
}
@Override
public DBOptions createStatistics() {
public DBOptions setStatistics(final Statistics statistics) {
assert(isOwningHandle());
createStatistics(nativeHandle_);
setStatistics(nativeHandle_, statistics.nativeHandle_);
return this;
}
@Override
public Statistics statisticsPtr() {
public Statistics statistics() {
assert(isOwningHandle());
long statsPtr = statisticsPtr(nativeHandle_);
if(statsPtr == 0) {
createStatistics();
statsPtr = statisticsPtr(nativeHandle_);
final long statisticsNativeHandle = statistics(nativeHandle_);
if(statisticsNativeHandle == 0) {
return null;
} else {
return new Statistics(statisticsNativeHandle);
}
return new Statistics(statsPtr);
}
@Override
@ -973,8 +971,8 @@ public class DBOptions
private native void setMaxTotalWalSize(long handle,
long maxTotalWalSize);
private native long maxTotalWalSize(long handle);
private native void createStatistics(long optHandle);
private native long statisticsPtr(long optHandle);
private native void setStatistics(final long handle, final long statisticsHandle);
private native long statistics(final long handle);
private native boolean useFsync(long handle);
private native void setUseFsync(long handle, boolean useFsync);
private native void setDbPaths(final long handle, final String[] paths,

@ -265,23 +265,22 @@ public interface DBOptionsInterface<T extends DBOptionsInterface> {
long maxTotalWalSize();
/**
* <p>Creates statistics object which collects metrics about database operations.
* <p>Sets the statistics object which collects metrics about database operations.
* Statistics objects should not be shared between DB instances as
* it does not use any locks to prevent concurrent updates.</p>
*
* @return the instance of the current object.
* @see RocksDB#open(org.rocksdb.Options, String)
*/
T createStatistics();
T setStatistics(final Statistics statistics);
/**
* <p>Returns statistics object. Calls {@link #createStatistics()} if
* C++ returns {@code nullptr} for statistics.</p>
* <p>Returns statistics object.</p>
*
* @return the instance of the statistics object.
* @see #createStatistics()
* @return the instance of the statistics object or null if there is no statistics object.
* @see #setStatistics(Statistics)
*/
Statistics statisticsPtr();
Statistics statistics();
/**
* <p>If true, then every store to stable storage will issue a fsync.</p>

@ -6,51 +6,93 @@
package org.rocksdb;
public enum HistogramType {
DB_GET(0),
DB_WRITE(1),
COMPACTION_TIME(2),
SUBCOMPACTION_SETUP_TIME(3),
TABLE_SYNC_MICROS(4),
COMPACTION_OUTFILE_SYNC_MICROS(5),
WAL_FILE_SYNC_MICROS(6),
MANIFEST_FILE_SYNC_MICROS(7),
// TIME SPENT IN IO DURING TABLE OPEN
TABLE_OPEN_IO_MICROS(8),
DB_MULTIGET(9),
READ_BLOCK_COMPACTION_MICROS(10),
READ_BLOCK_GET_MICROS(11),
WRITE_RAW_BLOCK_MICROS(12),
STALL_L0_SLOWDOWN_COUNT(13),
STALL_MEMTABLE_COMPACTION_COUNT(14),
STALL_L0_NUM_FILES_COUNT(15),
HARD_RATE_LIMIT_DELAY_COUNT(16),
SOFT_RATE_LIMIT_DELAY_COUNT(17),
NUM_FILES_IN_SINGLE_COMPACTION(18),
DB_SEEK(19),
WRITE_STALL(20),
SST_READ_MICROS(21),
// The number of subcompactions actually scheduled during a compaction
NUM_SUBCOMPACTIONS_SCHEDULED(22),
// Value size distribution in each operation
BYTES_PER_READ(23),
BYTES_PER_WRITE(24),
BYTES_PER_MULTIGET(25),
// number of bytes compressed/decompressed
// number of bytes is when uncompressed; i.e. before/after respectively
BYTES_COMPRESSED(26),
BYTES_DECOMPRESSED(27),
COMPRESSION_TIMES_NANOS(28),
DECOMPRESSION_TIMES_NANOS(29),
READ_NUM_MERGE_OPERANDS(30);
private final int value_;
private HistogramType(int value) {
value_ = value;
DB_GET((byte) 0x0),
DB_WRITE((byte) 0x1),
COMPACTION_TIME((byte) 0x2),
SUBCOMPACTION_SETUP_TIME((byte) 0x3),
TABLE_SYNC_MICROS((byte) 0x4),
COMPACTION_OUTFILE_SYNC_MICROS((byte) 0x5),
WAL_FILE_SYNC_MICROS((byte) 0x6),
MANIFEST_FILE_SYNC_MICROS((byte) 0x7),
/**
* TIME SPENT IN IO DURING TABLE OPEN.
*/
TABLE_OPEN_IO_MICROS((byte) 0x8),
DB_MULTIGET((byte) 0x9),
READ_BLOCK_COMPACTION_MICROS((byte) 0xA),
READ_BLOCK_GET_MICROS((byte) 0xB),
WRITE_RAW_BLOCK_MICROS((byte) 0xC),
STALL_L0_SLOWDOWN_COUNT((byte) 0xD),
STALL_MEMTABLE_COMPACTION_COUNT((byte) 0xE),
STALL_L0_NUM_FILES_COUNT((byte) 0xF),
HARD_RATE_LIMIT_DELAY_COUNT((byte) 0x10),
SOFT_RATE_LIMIT_DELAY_COUNT((byte) 0x11),
NUM_FILES_IN_SINGLE_COMPACTION((byte) 0x12),
DB_SEEK((byte) 0x13),
WRITE_STALL((byte) 0x14),
SST_READ_MICROS((byte) 0x15),
/**
* The number of subcompactions actually scheduled during a compaction.
*/
NUM_SUBCOMPACTIONS_SCHEDULED((byte) 0x16),
/**
* Value size distribution in each operation.
*/
BYTES_PER_READ((byte) 0x17),
BYTES_PER_WRITE((byte) 0x18),
BYTES_PER_MULTIGET((byte) 0x19),
/**
* number of bytes compressed.
*/
BYTES_COMPRESSED((byte) 0x1A),
/**
* number of bytes decompressed.
*
* number of bytes is when uncompressed; i.e. before/after respectively
*/
BYTES_DECOMPRESSED((byte) 0x1B),
COMPRESSION_TIMES_NANOS((byte) 0x1C),
DECOMPRESSION_TIMES_NANOS((byte) 0x1D),
READ_NUM_MERGE_OPERANDS((byte) 0x1E),
HISTOGRAM_ENUM_MAX((byte) 0x1F);
private final byte value;
HistogramType(final byte value) {
this.value = value;
}
public int getValue() {
return value_;
public byte getValue() {
return value;
}
}

@ -32,7 +32,7 @@ public enum InfoLogLevel {
*
* @param value byte representation of InfoLogLevel.
*
* @return {@link org.rocksdb.InfoLogLevel} instance or null.
* @return {@link org.rocksdb.InfoLogLevel} instance.
* @throws java.lang.IllegalArgumentException if an invalid
* value is provided.
*/

@ -379,23 +379,21 @@ public class Options extends RocksObject
}
@Override
public Options createStatistics() {
public Options setStatistics(final Statistics statistics) {
assert(isOwningHandle());
createStatistics(nativeHandle_);
setStatistics(nativeHandle_, statistics.nativeHandle_);
return this;
}
@Override
public Statistics statisticsPtr() {
public Statistics statistics() {
assert(isOwningHandle());
long statsPtr = statisticsPtr(nativeHandle_);
if(statsPtr == 0) {
createStatistics();
statsPtr = statisticsPtr(nativeHandle_);
final long statisticsNativeHandle = statistics(nativeHandle_);
if(statisticsNativeHandle == 0) {
return null;
} else {
return new Statistics(statisticsNativeHandle);
}
return new Statistics(statsPtr);
}
@Override
@ -1566,8 +1564,8 @@ public class Options extends RocksObject
final int maxFileOpeningThreads);
private native int maxFileOpeningThreads(final long handle);
private native long maxTotalWalSize(long handle);
private native void createStatistics(long optHandle);
private native long statisticsPtr(long optHandle);
private native void setStatistics(final long handle, final long statisticsHandle);
private native long statistics(final long handle);
private native boolean useFsync(long handle);
private native void setUseFsync(long handle, boolean useFsync);
private native void setDbPaths(final long handle, final String[] paths,

@ -5,33 +5,145 @@
package org.rocksdb;
import java.util.EnumSet;
/**
* Statistics to analyze the performance of a db. Pointer for statistics object
* is managed by Options class.
*/
public class Statistics {
public class Statistics extends RocksObject {
public Statistics() {
super(newStatistics());
}
public Statistics(final Statistics otherStatistics) {
super(newStatistics(otherStatistics.nativeHandle_));
}
public Statistics(final EnumSet<HistogramType> ignoreHistograms) {
super(newStatistics(toArrayValues(ignoreHistograms)));
}
public Statistics(final EnumSet<HistogramType> ignoreHistograms, final Statistics otherStatistics) {
super(newStatistics(toArrayValues(ignoreHistograms), otherStatistics.nativeHandle_));
}
/**
* Intentionally package-private.
*
* Used from {@link DBOptions#statistics()}
*
* @param existingStatisticsHandle The C++ pointer to an existing statistics object
*/
Statistics(final long existingStatisticsHandle) {
super(existingStatisticsHandle);
}
private final long statsHandle_;
private static byte[] toArrayValues(final EnumSet<HistogramType> histogramTypes) {
final byte[] values = new byte[histogramTypes.size()];
int i = 0;
for(final HistogramType histogramType : histogramTypes) {
values[i++] = histogramType.getValue();
}
return values;
}
/**
* Gets the current stats level.
*
* @return The stats level.
*/
public StatsLevel statsLevel() {
return StatsLevel.getStatsLevel(statsLevel(nativeHandle_));
}
public Statistics(final long statsHandle) {
statsHandle_ = statsHandle;
/**
* Sets the stats level.
*
* @param statsLevel The stats level to set.
*/
public void setStatsLevel(final StatsLevel statsLevel) {
setStatsLevel(nativeHandle_, statsLevel.getValue());
}
public long getTickerCount(TickerType tickerType) {
assert(isInitialized());
return getTickerCount0(tickerType.getValue(), statsHandle_);
/**
* Get the count for a ticker.
*
* @param tickerType The ticker to get the count for
*
* @return The count for the ticker
*/
public long getTickerCount(final TickerType tickerType) {
assert(isOwningHandle());
return getTickerCount(nativeHandle_, tickerType.getValue());
}
/**
* Get the count for a ticker and reset the tickers count.
*
* @param tickerType The ticker to get the count for
*
* @return The count for the ticker
*/
public long getAndResetTickerCount(final TickerType tickerType) {
assert(isOwningHandle());
return getAndResetTickerCount(nativeHandle_, tickerType.getValue());
}
/**
* Gets the histogram data for a particular histogram.
*
* @param histogramType The histogram to retrieve the data for
*
* @return The histogram data
*/
public HistogramData getHistogramData(final HistogramType histogramType) {
assert(isInitialized());
return getHistogramData0(
histogramType.getValue(), statsHandle_);
assert(isOwningHandle());
return getHistogramData(nativeHandle_, histogramType.getValue());
}
private boolean isInitialized() {
return (statsHandle_ != 0);
/**
* Gets a string representation of a particular histogram.
*
* @param histogramType The histogram to retrieve the data for
*
* @return A string representation of the histogram data
*/
public String getHistogramString(final HistogramType histogramType) {
assert(isOwningHandle());
return getHistogramString(nativeHandle_, histogramType.getValue());
}
private native long getTickerCount0(int tickerType, long handle);
private native HistogramData getHistogramData0(int histogramType, long handle);
/**
* Resets all ticker and histogram stats.
*/
public void reset() throws RocksDBException {
assert(isOwningHandle());
reset(nativeHandle_);
}
/**
* String representation of the statistic object.
*/
public String toString() {
assert(isOwningHandle());
return toString(nativeHandle_);
}
private native static long newStatistics();
private native static long newStatistics(final long otherStatisticsHandle);
private native static long newStatistics(final byte[] ignoreHistograms);
private native static long newStatistics(final byte[] ignoreHistograms, final long otherStatisticsHandle);
@Override protected final native void disposeInternal(final long handle);
private native byte statsLevel(final long handle);
private native void setStatsLevel(final long handle, final byte statsLevel);
private native long getTickerCount(final long handle, final byte tickerType);
private native long getAndResetTickerCount(final long handle, final byte tickerType);
private native HistogramData getHistogramData(final long handle, final byte histogramType);
private native String getHistogramString(final long handle, final byte histogramType);
private native void reset(final long nativeHandle) throws RocksDBException;
private native String toString(final long nativeHandle);
}

@ -71,33 +71,37 @@ public class StatisticsCollector {
if(Thread.currentThread().isInterrupted()) {
break;
}
for(StatsCollectorInput statsCollectorInput :
for(final StatsCollectorInput statsCollectorInput :
_statsCollectorInputList) {
Statistics statistics = statsCollectorInput.getStatistics();
StatisticsCollectorCallback statsCallback =
statsCollectorInput.getCallback();
// Collect ticker data
for(TickerType ticker : TickerType.values()) {
long tickerValue = statistics.getTickerCount(ticker);
statsCallback.tickerCallback(ticker, tickerValue);
// Collect ticker data
for(final TickerType ticker : TickerType.values()) {
if(ticker != TickerType.TICKER_ENUM_MAX) {
final long tickerValue = statistics.getTickerCount(ticker);
statsCallback.tickerCallback(ticker, tickerValue);
}
}
// Collect histogram data
for(HistogramType histogramType : HistogramType.values()) {
HistogramData histogramData =
statistics.getHistogramData(histogramType);
statsCallback.histogramCallback(histogramType, histogramData);
for(final HistogramType histogramType : HistogramType.values()) {
if(histogramType != HistogramType.HISTOGRAM_ENUM_MAX) {
final HistogramData histogramData =
statistics.getHistogramData(histogramType);
statsCallback.histogramCallback(histogramType, histogramData);
}
}
Thread.sleep(_statsCollectionInterval);
}
}
catch (InterruptedException e) {
catch (final InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
catch (Exception e) {
catch (final Exception e) {
throw new RuntimeException("Error while calculating statistics", e);
}
}

@ -0,0 +1,65 @@
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
package org.rocksdb;
/**
* The level of Statistics to report.
*/
public enum StatsLevel {
/**
* Collect all stats except time inside mutex lock AND time spent on
* compression.
*/
EXCEPT_DETAILED_TIMERS((byte) 0x0),
/**
* Collect all stats except the counters requiring to get time inside the
* mutex lock.
*/
EXCEPT_TIME_FOR_MUTEX((byte) 0x1),
/**
* Collect all stats, including measuring duration of mutex operations.
*
* If getting time is expensive on the platform to run, it can
* reduce scalability to more threads, especially for writes.
*/
ALL((byte) 0x2);
private final byte value;
StatsLevel(final byte value) {
this.value = value;
}
/**
* <p>Returns the byte value of the enumerations value.</p>
*
* @return byte representation
*/
public byte getValue() {
return value;
}
/**
* Get StatsLevel by byte value.
*
* @param value byte representation of StatsLevel.
*
* @return {@link org.rocksdb.StatsLevel} instance.
* @throws java.lang.IllegalArgumentException if an invalid
* value is provided.
*/
public static StatsLevel getStatsLevel(final byte value) {
for (final StatsLevel statsLevel : StatsLevel.values()) {
if (statsLevel.getValue() == value){
return statsLevel;
}
}
throw new IllegalArgumentException(
"Illegal value provided for InfoLogLevel.");
}
}

@ -6,211 +6,475 @@
package org.rocksdb;
public enum TickerType {
// total block cache misses
// REQUIRES: BLOCK_CACHE_MISS == BLOCK_CACHE_INDEX_MISS +
// BLOCK_CACHE_FILTER_MISS +
// BLOCK_CACHE_DATA_MISS;
BLOCK_CACHE_MISS(0),
// total block cache hit
// REQUIRES: BLOCK_CACHE_HIT == BLOCK_CACHE_INDEX_HIT +
// BLOCK_CACHE_FILTER_HIT +
// BLOCK_CACHE_DATA_HIT;
BLOCK_CACHE_HIT(1),
// # of blocks added to block cache.
BLOCK_CACHE_ADD(2),
// # of failures when adding blocks to block cache.
BLOCK_CACHE_ADD_FAILURES(3),
// # of times cache miss when accessing index block from block cache.
BLOCK_CACHE_INDEX_MISS(4),
// # of times cache hit when accessing index block from block cache.
BLOCK_CACHE_INDEX_HIT(5),
// # of index blocks added to block cache.
BLOCK_CACHE_INDEX_ADD(6),
// # of bytes of index blocks inserted into cache
BLOCK_CACHE_INDEX_BYTES_INSERT(7),
// # of bytes of index block erased from cache
BLOCK_CACHE_INDEX_BYTES_EVICT(8),
// # of times cache miss when accessing filter block from block cache.
BLOCK_CACHE_FILTER_MISS(9),
// # of times cache hit when accessing filter block from block cache.
BLOCK_CACHE_FILTER_HIT(10),
// # of filter blocks added to block cache.
BLOCK_CACHE_FILTER_ADD(11),
// # of bytes of bloom filter blocks inserted into cache
BLOCK_CACHE_FILTER_BYTES_INSERT(12),
// # of bytes of bloom filter block erased from cache
BLOCK_CACHE_FILTER_BYTES_EVICT(13),
// # of times cache miss when accessing data block from block cache.
BLOCK_CACHE_DATA_MISS(14),
// # of times cache hit when accessing data block from block cache.
BLOCK_CACHE_DATA_HIT(15),
// # of data blocks added to block cache.
BLOCK_CACHE_DATA_ADD(16),
// # of bytes of data blocks inserted into cache
BLOCK_CACHE_DATA_BYTES_INSERT(17),
// # of bytes read from cache.
BLOCK_CACHE_BYTES_READ(18),
// # of bytes written into cache.
BLOCK_CACHE_BYTES_WRITE(19),
// # of times bloom filter has avoided file reads.
BLOOM_FILTER_USEFUL(20),
// # persistent cache hit
PERSISTENT_CACHE_HIT(21),
// # persistent cache miss
PERSISTENT_CACHE_MISS(22),
// # total simulation block cache hits
SIM_BLOCK_CACHE_HIT(23),
// # total simulation block cache misses
SIM_BLOCK_CACHE_MISS(24),
// # of memtable hits.
MEMTABLE_HIT(25),
// # of memtable misses.
MEMTABLE_MISS(26),
// # of Get() queries served by L0
GET_HIT_L0(27),
// # of Get() queries served by L1
GET_HIT_L1(28),
// # of Get() queries served by L2 and up
GET_HIT_L2_AND_UP(29),
/**
* COMPACTION_KEY_DROP_* count the reasons for key drop during compaction
* There are 4 reasons currently.
*/
COMPACTION_KEY_DROP_NEWER_ENTRY(30), // key was written with a newer value.
// Also includes keys dropped for range del.
COMPACTION_KEY_DROP_OBSOLETE(31), // The key is obsolete.
COMPACTION_KEY_DROP_RANGE_DEL(32), // key was covered by a range tombstone.
COMPACTION_KEY_DROP_USER(33), // user compaction function has dropped the key.
COMPACTION_RANGE_DEL_DROP_OBSOLETE(34), // all keys in range were deleted.
// Number of keys written to the database via the Put and Write call's
NUMBER_KEYS_WRITTEN(35),
// Number of Keys read,
NUMBER_KEYS_READ(36),
// Number keys updated, if inplace update is enabled
NUMBER_KEYS_UPDATED(37),
// The number of uncompressed bytes issued by DB::Put(), DB::Delete(),
// DB::Merge(), and DB::Write().
BYTES_WRITTEN(38),
// The number of uncompressed bytes read from DB::Get(). It could be
// either from memtables, cache, or table files.
// For the number of logical bytes read from DB::MultiGet(),
// please use NUMBER_MULTIGET_BYTES_READ.
BYTES_READ(39),
// The number of calls to seek/next/prev
NUMBER_DB_SEEK(40),
NUMBER_DB_NEXT(41),
NUMBER_DB_PREV(42),
// The number of calls to seek/next/prev that returned data
NUMBER_DB_SEEK_FOUND(43),
NUMBER_DB_NEXT_FOUND(44),
NUMBER_DB_PREV_FOUND(45),
// The number of uncompressed bytes read from an iterator.
// Includes size of key and value.
ITER_BYTES_READ(46),
NO_FILE_CLOSES(47),
NO_FILE_OPENS(48),
NO_FILE_ERRORS(49),
// DEPRECATED Time system had to wait to do LO-L1 compactions
STALL_L0_SLOWDOWN_MICROS(50),
// DEPRECATED Time system had to wait to move memtable to L1.
STALL_MEMTABLE_COMPACTION_MICROS(51),
// DEPRECATED write throttle because of too many files in L0
STALL_L0_NUM_FILES_MICROS(52),
// Writer has to wait for compaction or flush to finish.
STALL_MICROS(53),
// The wait time for db mutex.
// Disabled by default. To enable it set stats level to kAll
DB_MUTEX_WAIT_MICROS(54),
RATE_LIMIT_DELAY_MILLIS(55),
NO_ITERATORS(56), // number of iterators currently open
// Number of MultiGet calls, keys read, and bytes read
NUMBER_MULTIGET_CALLS(57),
NUMBER_MULTIGET_KEYS_READ(58),
NUMBER_MULTIGET_BYTES_READ(59),
// Number of deletes records that were not required to be
// written to storage because key does not exist
NUMBER_FILTERED_DELETES(60),
NUMBER_MERGE_FAILURES(61),
// number of times bloom was checked before creating iterator on a
// file, and the number of times the check was useful in avoiding
// iterator creation (and thus likely IOPs).
BLOOM_FILTER_PREFIX_CHECKED(62),
BLOOM_FILTER_PREFIX_USEFUL(63),
// Number of times we had to reseek inside an iteration to skip
// over large number of keys with same userkey.
NUMBER_OF_RESEEKS_IN_ITERATION(64),
// Record the number of calls to GetUpadtesSince. Useful to keep track of
// transaction log iterator refreshes
GET_UPDATES_SINCE_CALLS(65),
BLOCK_CACHE_COMPRESSED_MISS(66), // miss in the compressed block cache
BLOCK_CACHE_COMPRESSED_HIT(67), // hit in the compressed block cache
// Number of blocks added to comopressed block cache
BLOCK_CACHE_COMPRESSED_ADD(68),
// Number of failures when adding blocks to compressed block cache
BLOCK_CACHE_COMPRESSED_ADD_FAILURES(69),
WAL_FILE_SYNCED(70), // Number of times WAL sync is done
WAL_FILE_BYTES(71), // Number of bytes written to WAL
// Writes can be processed by requesting thread or by the thread at the
// head of the writers queue.
WRITE_DONE_BY_SELF(72),
WRITE_DONE_BY_OTHER(73), // Equivalent to writes done for others
WRITE_TIMEDOUT(74), // Number of writes ending up with timed-out.
WRITE_WITH_WAL(75), // Number of Write calls that request WAL
COMPACT_READ_BYTES(76), // Bytes read during compaction
COMPACT_WRITE_BYTES(77), // Bytes written during compaction
FLUSH_WRITE_BYTES(78), // Bytes written during flush
// Number of table's properties loaded directly from file, without creating
// table reader object.
NUMBER_DIRECT_LOAD_TABLE_PROPERTIES(79),
NUMBER_SUPERVERSION_ACQUIRES(80),
NUMBER_SUPERVERSION_RELEASES(81),
NUMBER_SUPERVERSION_CLEANUPS(82),
// # of compressions/decompressions executed
NUMBER_BLOCK_COMPRESSED(83),
NUMBER_BLOCK_DECOMPRESSED(84),
NUMBER_BLOCK_NOT_COMPRESSED(85),
MERGE_OPERATION_TOTAL_TIME(86),
FILTER_OPERATION_TOTAL_TIME(87),
// Row cache.
ROW_CACHE_HIT(88),
ROW_CACHE_MISS(89),
// Read amplification statistics.
// Read amplification can be calculated using this formula
// (READ_AMP_TOTAL_READ_BYTES / READ_AMP_ESTIMATE_USEFUL_BYTES)
//
// REQUIRES: ReadOptions::read_amp_bytes_per_bit to be enabled
READ_AMP_ESTIMATE_USEFUL_BYTES(90), // Estimate of total bytes actually used.
READ_AMP_TOTAL_READ_BYTES(91), // Total size of loaded data blocks.
// Number of refill intervals where rate limiter's bytes are fully consumed.
NUMBER_RATE_LIMITER_DRAINS(92);
private final int value_;
private TickerType(int value) {
value_ = value;
}
public int getValue() {
return value_;
}
/**
* total block cache misses
*
* REQUIRES: BLOCK_CACHE_MISS == BLOCK_CACHE_INDEX_MISS +
* BLOCK_CACHE_FILTER_MISS +
* BLOCK_CACHE_DATA_MISS;
*/
BLOCK_CACHE_MISS((byte) 0x0),
/**
* total block cache hit
*
* REQUIRES: BLOCK_CACHE_HIT == BLOCK_CACHE_INDEX_HIT +
* BLOCK_CACHE_FILTER_HIT +
* BLOCK_CACHE_DATA_HIT;
*/
BLOCK_CACHE_HIT((byte) 0x1),
BLOCK_CACHE_ADD((byte) 0x2),
/**
* # of failures when adding blocks to block cache.
*/
BLOCK_CACHE_ADD_FAILURES((byte) 0x3),
/**
* # of times cache miss when accessing index block from block cache.
*/
BLOCK_CACHE_INDEX_MISS((byte) 0x4),
/**
* # of times cache hit when accessing index block from block cache.
*/
BLOCK_CACHE_INDEX_HIT((byte) 0x5),
/**
* # of index blocks added to block cache.
*/
BLOCK_CACHE_INDEX_ADD((byte) 0x6),
/**
* # of bytes of index blocks inserted into cache
*/
BLOCK_CACHE_INDEX_BYTES_INSERT((byte) 0x7),
/**
* # of bytes of index block erased from cache
*/
BLOCK_CACHE_INDEX_BYTES_EVICT((byte) 0x8),
/**
* # of times cache miss when accessing filter block from block cache.
*/
BLOCK_CACHE_FILTER_MISS((byte) 0x9),
/**
* # of times cache hit when accessing filter block from block cache.
*/
BLOCK_CACHE_FILTER_HIT((byte) 0xA),
/**
* # of filter blocks added to block cache.
*/
BLOCK_CACHE_FILTER_ADD((byte) 0xB),
/**
* # of bytes of bloom filter blocks inserted into cache
*/
BLOCK_CACHE_FILTER_BYTES_INSERT((byte) 0xC),
/**
* # of bytes of bloom filter block erased from cache
*/
BLOCK_CACHE_FILTER_BYTES_EVICT((byte) 0xD),
/**
* # of times cache miss when accessing data block from block cache.
*/
BLOCK_CACHE_DATA_MISS((byte) 0xE),
/**
* # of times cache hit when accessing data block from block cache.
*/
BLOCK_CACHE_DATA_HIT((byte) 0xF),
/**
* # of data blocks added to block cache.
*/
BLOCK_CACHE_DATA_ADD((byte) 0x10),
/**
* # of bytes of data blocks inserted into cache
*/
BLOCK_CACHE_DATA_BYTES_INSERT((byte) 0x11),
/**
* # of bytes read from cache.
*/
BLOCK_CACHE_BYTES_READ((byte) 0x12),
/**
* # of bytes written into cache.
*/
BLOCK_CACHE_BYTES_WRITE((byte) 0x13),
/**
* # of times bloom filter has avoided file reads.
*/
BLOOM_FILTER_USEFUL((byte) 0x14),
/**
* # persistent cache hit
*/
PERSISTENT_CACHE_HIT((byte) 0x15),
/**
* # persistent cache miss
*/
PERSISTENT_CACHE_MISS((byte) 0x16),
/**
* # total simulation block cache hits
*/
SIM_BLOCK_CACHE_HIT((byte) 0x17),
/**
* # total simulation block cache misses
*/
SIM_BLOCK_CACHE_MISS((byte) 0x18),
/**
* # of memtable hits.
*/
MEMTABLE_HIT((byte) 0x19),
/**
* # of memtable misses.
*/
MEMTABLE_MISS((byte) 0x1A),
/**
* # of Get() queries served by L0
*/
GET_HIT_L0((byte) 0x1B),
/**
* # of Get() queries served by L1
*/
GET_HIT_L1((byte) 0x1C),
/**
* # of Get() queries served by L2 and up
*/
GET_HIT_L2_AND_UP((byte) 0x1D),
/**
* COMPACTION_KEY_DROP_* count the reasons for key drop during compaction
* There are 4 reasons currently.
*/
/**
* key was written with a newer value.
*/
COMPACTION_KEY_DROP_NEWER_ENTRY((byte) 0x1E),
/**
* Also includes keys dropped for range del.
* The key is obsolete.
*/
COMPACTION_KEY_DROP_OBSOLETE((byte) 0x1F),
/**
* key was covered by a range tombstone.
*/
COMPACTION_KEY_DROP_RANGE_DEL((byte) 0x20),
/**
* User compaction function has dropped the key.
*/
COMPACTION_KEY_DROP_USER((byte) 0x21),
/**
* all keys in range were deleted.
*/
COMPACTION_RANGE_DEL_DROP_OBSOLETE((byte) 0x22),
/**
* Number of keys written to the database via the Put and Write call's.
*/
NUMBER_KEYS_WRITTEN((byte) 0x23),
/**
* Number of Keys read.
*/
NUMBER_KEYS_READ((byte) 0x24),
/**
* Number keys updated, if inplace update is enabled
*/
NUMBER_KEYS_UPDATED((byte) 0x25),
/**
* The number of uncompressed bytes issued by DB::Put(), DB::Delete(),\
* DB::Merge(), and DB::Write().
*/
BYTES_WRITTEN((byte) 0x26),
/**
* The number of uncompressed bytes read from DB::Get(). It could be
* either from memtables, cache, or table files.
*
* For the number of logical bytes read from DB::MultiGet(),
* please use {@link #NUMBER_MULTIGET_BYTES_READ}.
*/
BYTES_READ((byte) 0x27),
/**
* The number of calls to seek.
*/
NUMBER_DB_SEEK((byte) 0x28),
/**
* The number of calls to next.
*/
NUMBER_DB_NEXT((byte) 0x29),
/**
* The number of calls to prev.
*/
NUMBER_DB_PREV((byte) 0x2A),
/**
* The number of calls to seek that returned data.
*/
NUMBER_DB_SEEK_FOUND((byte) 0x2B),
/**
* The number of calls to next that returned data.
*/
NUMBER_DB_NEXT_FOUND((byte) 0x2C),
/**
* The number of calls to prev that returned data.
*/
NUMBER_DB_PREV_FOUND((byte) 0x2D),
/**
* The number of uncompressed bytes read from an iterator.
* Includes size of key and value.
*/
ITER_BYTES_READ((byte) 0x2E),
NO_FILE_CLOSES((byte) 0x2F),
NO_FILE_OPENS((byte) 0x30),
NO_FILE_ERRORS((byte) 0x31),
/**
* Time system had to wait to do LO-L1 compactions.
*
* @deprecated
*/
@Deprecated
STALL_L0_SLOWDOWN_MICROS((byte) 0x32),
/**
* Time system had to wait to move memtable to L1.
*
* @deprecated
*/
@Deprecated
STALL_MEMTABLE_COMPACTION_MICROS((byte) 0x33),
/**
* write throttle because of too many files in L0.
*
* @deprecated
*/
@Deprecated
STALL_L0_NUM_FILES_MICROS((byte) 0x34),
/**
* Writer has to wait for compaction or flush to finish.
*/
STALL_MICROS((byte) 0x35),
/**
* The wait time for db mutex.
*
* Disabled by default. To enable it set stats level to {@link StatsLevel#ALL}
*/
DB_MUTEX_WAIT_MICROS((byte) 0x36),
RATE_LIMIT_DELAY_MILLIS((byte) 0x37),
/**
* Number of iterators currently open.
*/
NO_ITERATORS((byte) 0x38),
/**
* Number of MultiGet calls.
*/
NUMBER_MULTIGET_CALLS((byte) 0x39),
/**
* Number of MultiGet keys read.
*/
NUMBER_MULTIGET_KEYS_READ((byte) 0x3A),
/**
* Number of MultiGet bytes read.
*/
NUMBER_MULTIGET_BYTES_READ((byte) 0x3B),
/**
* Number of deletes records that were not required to be
* written to storage because key does not exist.
*/
NUMBER_FILTERED_DELETES((byte) 0x3C),
NUMBER_MERGE_FAILURES((byte) 0x3D),
/**
* Number of times bloom was checked before creating iterator on a
* file, and the number of times the check was useful in avoiding
* iterator creation (and thus likely IOPs).
*/
BLOOM_FILTER_PREFIX_CHECKED((byte) 0x3E),
BLOOM_FILTER_PREFIX_USEFUL((byte) 0x3F),
/**
* Number of times we had to reseek inside an iteration to skip
* over large number of keys with same userkey.
*/
NUMBER_OF_RESEEKS_IN_ITERATION((byte) 0x40),
/**
* Record the number of calls to {@link RocksDB#getUpdatesSince(long)}. Useful to keep track of
* transaction log iterator refreshes.
*/
GET_UPDATES_SINCE_CALLS((byte) 0x41),
/**
* Miss in the compressed block cache.
*/
BLOCK_CACHE_COMPRESSED_MISS((byte) 0x42),
/**
* Hit in the compressed block cache.
*/
BLOCK_CACHE_COMPRESSED_HIT((byte) 0x43),
/**
* Number of blocks added to compressed block cache.
*/
BLOCK_CACHE_COMPRESSED_ADD((byte) 0x44),
/**
* Number of failures when adding blocks to compressed block cache.
*/
BLOCK_CACHE_COMPRESSED_ADD_FAILURES((byte) 0x45),
/**
* Number of times WAL sync is done.
*/
WAL_FILE_SYNCED((byte) 0x46),
/**
* Number of bytes written to WAL.
*/
WAL_FILE_BYTES((byte) 0x47),
/**
* Writes can be processed by requesting thread or by the thread at the
* head of the writers queue.
*/
WRITE_DONE_BY_SELF((byte) 0x48),
/**
* Equivalent to writes done for others.
*/
WRITE_DONE_BY_OTHER((byte) 0x49),
/**
* Number of writes ending up with timed-out.
*/
WRITE_TIMEDOUT((byte) 0x4A),
/**
* Number of Write calls that request WAL.
*/
WRITE_WITH_WAL((byte) 0x4B),
/**
* Bytes read during compaction.
*/
COMPACT_READ_BYTES((byte) 0x4C),
/**
* Bytes written during compaction.
*/
COMPACT_WRITE_BYTES((byte) 0x4D),
/**
* Bytes written during flush.
*/
FLUSH_WRITE_BYTES((byte) 0x4E),
/**
* Number of table's properties loaded directly from file, without creating
* table reader object.
*/
NUMBER_DIRECT_LOAD_TABLE_PROPERTIES((byte) 0x4F),
NUMBER_SUPERVERSION_ACQUIRES((byte) 0x50),
NUMBER_SUPERVERSION_RELEASES((byte) 0x51),
NUMBER_SUPERVERSION_CLEANUPS((byte) 0x52),
/**
* # of compressions/decompressions executed
*/
NUMBER_BLOCK_COMPRESSED((byte) 0x53),
NUMBER_BLOCK_DECOMPRESSED((byte) 0x54),
NUMBER_BLOCK_NOT_COMPRESSED((byte) 0x55),
MERGE_OPERATION_TOTAL_TIME((byte) 0x56),
FILTER_OPERATION_TOTAL_TIME((byte) 0x57),
/**
* Row cache.
*/
ROW_CACHE_HIT((byte) 0x58),
ROW_CACHE_MISS((byte) 0x59),
/**
* Read amplification statistics.
*
* Read amplification can be calculated using this formula
* (READ_AMP_TOTAL_READ_BYTES / READ_AMP_ESTIMATE_USEFUL_BYTES)
*
* REQUIRES: ReadOptions::read_amp_bytes_per_bit to be enabled
*/
/**
* Estimate of total bytes actually used.
*/
READ_AMP_ESTIMATE_USEFUL_BYTES((byte) 0x5A),
/**
* Total size of loaded data blocks.
*/
READ_AMP_TOTAL_READ_BYTES((byte) 0x5B),
/**
* Number of refill intervals where rate limiter's bytes are fully consumed.
*/
NUMBER_RATE_LIMITER_DRAINS((byte) 0x5C),
TICKER_ENUM_MAX((byte) 0x5D);
private final byte value;
TickerType(final byte value) {
this.value = value;
}
public byte getValue() {
return value;
}
}

@ -624,14 +624,14 @@ public class DBOptionsTest {
@Test
public void statistics() {
try(final DBOptions options = new DBOptions()) {
Statistics statistics = options.createStatistics().
statisticsPtr();
assertThat(statistics).isNotNull();
final Statistics statistics = options.statistics();
assertThat(statistics).isNull();
}
try(final DBOptions anotherOptions = new DBOptions()) {
statistics = anotherOptions.statisticsPtr();
assertThat(statistics).isNotNull();
}
try(final Statistics statistics = new Statistics();
final DBOptions options = new DBOptions().setStatistics(statistics);
final Statistics stats = options.statistics()) {
assertThat(stats).isNotNull();
}
}
}

@ -1010,14 +1010,15 @@ public class OptionsTest {
@Test
public void statistics() {
try (final Options options = new Options()) {
Statistics statistics = options.createStatistics().
statisticsPtr();
assertThat(statistics).isNotNull();
try (final Options anotherOptions = new Options()) {
statistics = anotherOptions.statisticsPtr();
assertThat(statistics).isNotNull();
}
try(final Options options = new Options()) {
final Statistics statistics = options.statistics();
assertThat(statistics).isNull();
}
try(final Statistics statistics = new Statistics();
final Options options = new Options().setStatistics(statistics);
final Statistics stats = options.statistics()) {
assertThat(stats).isNotNull();
}
}

@ -26,27 +26,30 @@ public class StatisticsCollectorTest {
@Test
public void statisticsCollector()
throws InterruptedException, RocksDBException {
try (final Options opt = new Options()
.createStatistics()
try (final Statistics statistics = new Statistics();
final Options opt = new Options()
.setStatistics(statistics)
.setCreateIfMissing(true);
final RocksDB db = RocksDB.open(opt,
dbFolder.getRoot().getAbsolutePath())) {
final Statistics stats = opt.statisticsPtr();
final StatsCallbackMock callback = new StatsCallbackMock();
final StatsCollectorInput statsInput =
new StatsCollectorInput(stats, callback);
try(final Statistics stats = opt.statistics()) {
final StatisticsCollector statsCollector = new StatisticsCollector(
Collections.singletonList(statsInput), 100);
statsCollector.start();
final StatsCallbackMock callback = new StatsCallbackMock();
final StatsCollectorInput statsInput =
new StatsCollectorInput(stats, callback);
Thread.sleep(1000);
final StatisticsCollector statsCollector = new StatisticsCollector(
Collections.singletonList(statsInput), 100);
statsCollector.start();
assertThat(callback.tickerCallbackCount).isGreaterThan(0);
assertThat(callback.histCallbackCount).isGreaterThan(0);
Thread.sleep(1000);
statsCollector.shutDown(1000);
assertThat(callback.tickerCallbackCount).isGreaterThan(0);
assertThat(callback.histCallbackCount).isGreaterThan(0);
statsCollector.shutDown(1000);
}
}
}
}

@ -0,0 +1,160 @@
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
package org.rocksdb;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import java.nio.charset.StandardCharsets;
import static org.assertj.core.api.Assertions.assertThat;
public class StatisticsTest {
@ClassRule
public static final RocksMemoryResource rocksMemoryResource =
new RocksMemoryResource();
@Rule
public TemporaryFolder dbFolder = new TemporaryFolder();
@Test
public void statsLevel() throws RocksDBException {
final Statistics statistics = new Statistics();
statistics.setStatsLevel(StatsLevel.ALL);
assertThat(statistics.statsLevel()).isEqualTo(StatsLevel.ALL);
}
@Test
public void getTickerCount() throws RocksDBException {
try (final Statistics statistics = new Statistics();
final Options opt = new Options()
.setStatistics(statistics)
.setCreateIfMissing(true);
final RocksDB db = RocksDB.open(opt,
dbFolder.getRoot().getAbsolutePath())) {
final byte[] key = "some-key".getBytes(StandardCharsets.UTF_8);
final byte[] value = "some-value".getBytes(StandardCharsets.UTF_8);
db.put(key, value);
for(int i = 0; i < 10; i++) {
db.get(key);
}
assertThat(statistics.getTickerCount(TickerType.BYTES_READ)).isGreaterThan(0);
}
}
@Test
public void getAndResetTickerCount() throws RocksDBException {
try (final Statistics statistics = new Statistics();
final Options opt = new Options()
.setStatistics(statistics)
.setCreateIfMissing(true);
final RocksDB db = RocksDB.open(opt,
dbFolder.getRoot().getAbsolutePath())) {
final byte[] key = "some-key".getBytes(StandardCharsets.UTF_8);
final byte[] value = "some-value".getBytes(StandardCharsets.UTF_8);
db.put(key, value);
for(int i = 0; i < 10; i++) {
db.get(key);
}
final long read = statistics.getAndResetTickerCount(TickerType.BYTES_READ);
assertThat(read).isGreaterThan(0);
final long readAfterReset = statistics.getTickerCount(TickerType.BYTES_READ);
assertThat(readAfterReset).isLessThan(read);
}
}
@Test
public void getHistogramData() throws RocksDBException {
try (final Statistics statistics = new Statistics();
final Options opt = new Options()
.setStatistics(statistics)
.setCreateIfMissing(true);
final RocksDB db = RocksDB.open(opt,
dbFolder.getRoot().getAbsolutePath())) {
final byte[] key = "some-key".getBytes(StandardCharsets.UTF_8);
final byte[] value = "some-value".getBytes(StandardCharsets.UTF_8);
db.put(key, value);
for(int i = 0; i < 10; i++) {
db.get(key);
}
final HistogramData histogramData = statistics.getHistogramData(HistogramType.BYTES_PER_READ);
assertThat(histogramData).isNotNull();
assertThat(histogramData.getAverage()).isGreaterThan(0);
}
}
@Test
public void getHistogramString() throws RocksDBException {
try (final Statistics statistics = new Statistics();
final Options opt = new Options()
.setStatistics(statistics)
.setCreateIfMissing(true);
final RocksDB db = RocksDB.open(opt,
dbFolder.getRoot().getAbsolutePath())) {
final byte[] key = "some-key".getBytes(StandardCharsets.UTF_8);
final byte[] value = "some-value".getBytes(StandardCharsets.UTF_8);
for(int i = 0; i < 10; i++) {
db.put(key, value);
}
assertThat(statistics.getHistogramString(HistogramType.BYTES_PER_WRITE)).isNotNull();
}
}
@Test
public void reset() throws RocksDBException {
try (final Statistics statistics = new Statistics();
final Options opt = new Options()
.setStatistics(statistics)
.setCreateIfMissing(true);
final RocksDB db = RocksDB.open(opt,
dbFolder.getRoot().getAbsolutePath())) {
final byte[] key = "some-key".getBytes(StandardCharsets.UTF_8);
final byte[] value = "some-value".getBytes(StandardCharsets.UTF_8);
db.put(key, value);
for(int i = 0; i < 10; i++) {
db.get(key);
}
final long read = statistics.getTickerCount(TickerType.BYTES_READ);
assertThat(read).isGreaterThan(0);
statistics.reset();
final long readAfterReset = statistics.getTickerCount(TickerType.BYTES_READ);
assertThat(readAfterReset).isLessThan(read);
}
}
@Test
public void ToString() throws RocksDBException {
try (final Statistics statistics = new Statistics();
final Options opt = new Options()
.setStatistics(statistics)
.setCreateIfMissing(true);
final RocksDB db = RocksDB.open(opt,
dbFolder.getRoot().getAbsolutePath())) {
assertThat(statistics.toString()).isNotNull();
}
}
}

@ -386,6 +386,7 @@ JNI_NATIVE_SOURCES = \
java/rocksjni/snapshot.cc \
java/rocksjni/sst_file_writerjni.cc \
java/rocksjni/statistics.cc \
java/rocksjni/statisticsjni.cc \
java/rocksjni/table.cc \
java/rocksjni/transaction_log.cc \
java/rocksjni/ttl.cc \

Loading…
Cancel
Save