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/snapshot.cc
rocksjni/sst_file_writerjni.cc rocksjni/sst_file_writerjni.cc
rocksjni/statistics.cc rocksjni/statistics.cc
rocksjni/statisticsjni.cc
rocksjni/table.cc rocksjni/table.cc
rocksjni/transaction_log.cc rocksjni/transaction_log.cc
rocksjni/ttl.cc rocksjni/ttl.cc

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

@ -21,6 +21,7 @@
#include "rocksjni/comparatorjnicallback.h" #include "rocksjni/comparatorjnicallback.h"
#include "rocksjni/portal.h" #include "rocksjni/portal.h"
#include "rocksjni/statisticsjni.h"
#include "rocksdb/db.h" #include "rocksdb/db.h"
#include "rocksdb/options.h" #include "rocksdb/options.h"
@ -224,24 +225,34 @@ void Java_org_rocksdb_Options_setMaxWriteBufferNumber(
/* /*
* Class: org_rocksdb_Options * Class: org_rocksdb_Options
* Method: createStatistics * Method: setStatistics
* Signature: (J)V * Signature: (JJ)V
*/ */
void Java_org_rocksdb_Options_createStatistics( void Java_org_rocksdb_Options_setStatistics(
JNIEnv* env, jobject jobj, jlong jOptHandle) { JNIEnv* env, jobject jobj, jlong jhandle, jlong jstatistics_handle) {
reinterpret_cast<rocksdb::Options*>(jOptHandle)->statistics = auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle);
rocksdb::CreateDBStatistics(); auto* pSptr =
reinterpret_cast<std::shared_ptr<rocksdb::StatisticsJni>*>(
jstatistics_handle);
opt->statistics = *pSptr;
} }
/* /*
* Class: org_rocksdb_Options * Class: org_rocksdb_Options
* Method: statisticsPtr * Method: statistics
* Signature: (J)J * Signature: (J)J
*/ */
jlong Java_org_rocksdb_Options_statisticsPtr( jlong Java_org_rocksdb_Options_statistics(
JNIEnv* env, jobject jobj, jlong jOptHandle) { JNIEnv* env, jobject jobj, jlong jhandle) {
auto* st = reinterpret_cast<rocksdb::Options*>(jOptHandle)->statistics.get(); auto* opt = reinterpret_cast<rocksdb::Options*>(jhandle);
return reinterpret_cast<jlong>(st); 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 * Class: org_rocksdb_DBOptions
* Method: createStatistics * Method: setStatistics
* Signature: (J)V * Signature: (JJ)V
*/ */
void Java_org_rocksdb_DBOptions_createStatistics( void Java_org_rocksdb_DBOptions_setStatistics(
JNIEnv* env, jobject jobj, jlong jOptHandle) { JNIEnv* env, jobject jobj, jlong jhandle, jlong jstatistics_handle) {
reinterpret_cast<rocksdb::DBOptions*>(jOptHandle)->statistics = auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle);
rocksdb::CreateDBStatistics(); auto* pSptr =
reinterpret_cast<std::shared_ptr<rocksdb::StatisticsJni>*>(
jstatistics_handle);
opt->statistics = *pSptr;
} }
/* /*
* Class: org_rocksdb_DBOptions * Class: org_rocksdb_DBOptions
* Method: statisticsPtr * Method: statistics
* Signature: (J)J * Signature: (J)J
*/ */
jlong Java_org_rocksdb_DBOptions_statisticsPtr( jlong Java_org_rocksdb_DBOptions_statistics(
JNIEnv* env, jobject jobj, jlong jOptHandle) { JNIEnv* env, jobject jobj, jlong jhandle) {
auto* st = reinterpret_cast<rocksdb::DBOptions*>(jOptHandle)-> auto* opt = reinterpret_cast<rocksdb::DBOptions*>(jhandle);
statistics.get(); std::shared_ptr<rocksdb::Statistics> sptr = opt->statistics;
return reinterpret_cast<jlong>(st); 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 // various utility functions for working with RocksDB and JNI
class JniUtil { class JniUtil {
public: public:

@ -6,39 +6,178 @@
// This file implements the "bridge" between Java and C++ and enables // This file implements the "bridge" between Java and C++ and enables
// calling c++ rocksdb::Statistics methods from Java side. // calling c++ rocksdb::Statistics methods from Java side.
#include <stdio.h>
#include <stdlib.h>
#include <jni.h> #include <jni.h>
#include <memory>
#include <set>
#include "include/org_rocksdb_Statistics.h" #include "include/org_rocksdb_Statistics.h"
#include "rocksjni/portal.h" #include "rocksjni/portal.h"
#include "rocksjni/statisticsjni.h"
#include "rocksdb/statistics.h" #include "rocksdb/statistics.h"
/* /*
* Class: org_rocksdb_Statistics * Class: org_rocksdb_Statistics
* Method: getTickerCount0 * Method: newStatistics
* Signature: (IJ)J * Signature: ()J
*/ */
jlong Java_org_rocksdb_Statistics_getTickerCount0( jlong Java_org_rocksdb_Statistics_newStatistics__(JNIEnv* env, jclass jcls) {
JNIEnv* env, jobject jobj, jint tickerType, jlong handle) { return Java_org_rocksdb_Statistics_newStatistics___3BJ(
auto* st = reinterpret_cast<rocksdb::Statistics*>(handle); env, jcls, nullptr, 0);
assert(st != nullptr);
return st->getTickerCount(static_cast<rocksdb::Tickers>(tickerType));
} }
/* /*
* Class: org_rocksdb_Statistics * Class: org_rocksdb_Statistics
* Method: getHistogramData0 * Method: newStatistics
* Signature: (IJ)Lorg/rocksdb/HistogramData; * Signature: (J)J
*/ */
jobject Java_org_rocksdb_Statistics_getHistogramData0( jlong Java_org_rocksdb_Statistics_newStatistics__J(
JNIEnv* env, jobject jobj, jint histogramType, jlong handle) { JNIEnv* env, jclass jcls, jlong jother_statistics_handle) {
auto* st = reinterpret_cast<rocksdb::Statistics*>(handle); return Java_org_rocksdb_Statistics_newStatistics___3BJ(
assert(st != nullptr); 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; return reinterpret_cast<jlong>(pSptr_statistics);
st->histogramData(static_cast<rocksdb::Histograms>(histogramType), }
&data);
/*
* 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); jclass jclazz = rocksdb::HistogramDataJni::getJClass(env);
if(jclazz == nullptr) { if(jclazz == nullptr) {
@ -58,3 +197,48 @@ jobject Java_org_rocksdb_Statistics_getHistogramData0(
mid, data.median, data.percentile95,data.percentile99, data.average, mid, data.median, data.percentile95,data.percentile99, data.average,
data.standard_deviation); 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 @Override
public DBOptions createStatistics() { public DBOptions setStatistics(final Statistics statistics) {
assert(isOwningHandle()); assert(isOwningHandle());
createStatistics(nativeHandle_); setStatistics(nativeHandle_, statistics.nativeHandle_);
return this; return this;
} }
@Override @Override
public Statistics statisticsPtr() { public Statistics statistics() {
assert(isOwningHandle()); assert(isOwningHandle());
final long statisticsNativeHandle = statistics(nativeHandle_);
long statsPtr = statisticsPtr(nativeHandle_); if(statisticsNativeHandle == 0) {
if(statsPtr == 0) { return null;
createStatistics(); } else {
statsPtr = statisticsPtr(nativeHandle_); return new Statistics(statisticsNativeHandle);
} }
return new Statistics(statsPtr);
} }
@Override @Override
@ -973,8 +971,8 @@ public class DBOptions
private native void setMaxTotalWalSize(long handle, private native void setMaxTotalWalSize(long handle,
long maxTotalWalSize); long maxTotalWalSize);
private native long maxTotalWalSize(long handle); private native long maxTotalWalSize(long handle);
private native void createStatistics(long optHandle); private native void setStatistics(final long handle, final long statisticsHandle);
private native long statisticsPtr(long optHandle); private native long statistics(final long handle);
private native boolean useFsync(long handle); private native boolean useFsync(long handle);
private native void setUseFsync(long handle, boolean useFsync); private native void setUseFsync(long handle, boolean useFsync);
private native void setDbPaths(final long handle, final String[] paths, private native void setDbPaths(final long handle, final String[] paths,

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

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

@ -32,7 +32,7 @@ public enum InfoLogLevel {
* *
* @param value byte representation of 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 * @throws java.lang.IllegalArgumentException if an invalid
* value is provided. * value is provided.
*/ */

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

@ -5,33 +5,145 @@
package org.rocksdb; package org.rocksdb;
import java.util.EnumSet;
/** /**
* Statistics to analyze the performance of a db. Pointer for statistics object * Statistics to analyze the performance of a db. Pointer for statistics object
* is managed by Options class. * 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()); * Get the count for a ticker.
return getTickerCount0(tickerType.getValue(), statsHandle_); *
* @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) { public HistogramData getHistogramData(final HistogramType histogramType) {
assert(isInitialized()); assert(isOwningHandle());
return getHistogramData0( return getHistogramData(nativeHandle_, histogramType.getValue());
histogramType.getValue(), statsHandle_);
} }
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()) { if(Thread.currentThread().isInterrupted()) {
break; break;
} }
for(StatsCollectorInput statsCollectorInput : for(final StatsCollectorInput statsCollectorInput :
_statsCollectorInputList) { _statsCollectorInputList) {
Statistics statistics = statsCollectorInput.getStatistics(); Statistics statistics = statsCollectorInput.getStatistics();
StatisticsCollectorCallback statsCallback = StatisticsCollectorCallback statsCallback =
statsCollectorInput.getCallback(); statsCollectorInput.getCallback();
// Collect ticker data // Collect ticker data
for(TickerType ticker : TickerType.values()) { for(final TickerType ticker : TickerType.values()) {
long tickerValue = statistics.getTickerCount(ticker); if(ticker != TickerType.TICKER_ENUM_MAX) {
statsCallback.tickerCallback(ticker, tickerValue); final long tickerValue = statistics.getTickerCount(ticker);
statsCallback.tickerCallback(ticker, tickerValue);
}
} }
// Collect histogram data // Collect histogram data
for(HistogramType histogramType : HistogramType.values()) { for(final HistogramType histogramType : HistogramType.values()) {
HistogramData histogramData = if(histogramType != HistogramType.HISTOGRAM_ENUM_MAX) {
statistics.getHistogramData(histogramType); final HistogramData histogramData =
statsCallback.histogramCallback(histogramType, histogramData); statistics.getHistogramData(histogramType);
statsCallback.histogramCallback(histogramType, histogramData);
}
} }
Thread.sleep(_statsCollectionInterval); Thread.sleep(_statsCollectionInterval);
} }
} }
catch (InterruptedException e) { catch (final InterruptedException e) {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
break; break;
} }
catch (Exception e) { catch (final Exception e) {
throw new RuntimeException("Error while calculating statistics", 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; package org.rocksdb;
public enum TickerType { public enum TickerType {
// total block cache misses
// REQUIRES: BLOCK_CACHE_MISS == BLOCK_CACHE_INDEX_MISS + /**
// BLOCK_CACHE_FILTER_MISS + * total block cache misses
// BLOCK_CACHE_DATA_MISS; *
BLOCK_CACHE_MISS(0), * REQUIRES: BLOCK_CACHE_MISS == BLOCK_CACHE_INDEX_MISS +
// total block cache hit * BLOCK_CACHE_FILTER_MISS +
// REQUIRES: BLOCK_CACHE_HIT == BLOCK_CACHE_INDEX_HIT + * BLOCK_CACHE_DATA_MISS;
// BLOCK_CACHE_FILTER_HIT + */
// BLOCK_CACHE_DATA_HIT; BLOCK_CACHE_MISS((byte) 0x0),
BLOCK_CACHE_HIT(1),
// # of blocks added to block cache. /**
BLOCK_CACHE_ADD(2), * total block cache hit
// # of failures when adding blocks to block cache. *
BLOCK_CACHE_ADD_FAILURES(3), * REQUIRES: BLOCK_CACHE_HIT == BLOCK_CACHE_INDEX_HIT +
// # of times cache miss when accessing index block from block cache. * BLOCK_CACHE_FILTER_HIT +
BLOCK_CACHE_INDEX_MISS(4), * BLOCK_CACHE_DATA_HIT;
// # of times cache hit when accessing index block from block cache. */
BLOCK_CACHE_INDEX_HIT(5), BLOCK_CACHE_HIT((byte) 0x1),
// # of index blocks added to block cache.
BLOCK_CACHE_INDEX_ADD(6), BLOCK_CACHE_ADD((byte) 0x2),
// # of bytes of index blocks inserted into cache
BLOCK_CACHE_INDEX_BYTES_INSERT(7), /**
// # of bytes of index block erased from cache * # of failures when adding blocks to block cache.
BLOCK_CACHE_INDEX_BYTES_EVICT(8), */
// # of times cache miss when accessing filter block from block cache. BLOCK_CACHE_ADD_FAILURES((byte) 0x3),
BLOCK_CACHE_FILTER_MISS(9),
// # of times cache hit when accessing filter block from block cache. /**
BLOCK_CACHE_FILTER_HIT(10), * # of times cache miss when accessing index block from block cache.
// # of filter blocks added to block cache. */
BLOCK_CACHE_FILTER_ADD(11), BLOCK_CACHE_INDEX_MISS((byte) 0x4),
// # of bytes of bloom filter blocks inserted into cache
BLOCK_CACHE_FILTER_BYTES_INSERT(12), /**
// # of bytes of bloom filter block erased from cache * # of times cache hit when accessing index block from block cache.
BLOCK_CACHE_FILTER_BYTES_EVICT(13), */
// # of times cache miss when accessing data block from block cache. BLOCK_CACHE_INDEX_HIT((byte) 0x5),
BLOCK_CACHE_DATA_MISS(14),
// # of times cache hit when accessing data block from block cache. /**
BLOCK_CACHE_DATA_HIT(15), * # of index blocks added to block cache.
// # of data blocks added to block cache. */
BLOCK_CACHE_DATA_ADD(16), BLOCK_CACHE_INDEX_ADD((byte) 0x6),
// # of bytes of data blocks inserted into cache
BLOCK_CACHE_DATA_BYTES_INSERT(17), /**
// # of bytes read from cache. * # of bytes of index blocks inserted into cache
BLOCK_CACHE_BYTES_READ(18), */
// # of bytes written into cache. BLOCK_CACHE_INDEX_BYTES_INSERT((byte) 0x7),
BLOCK_CACHE_BYTES_WRITE(19),
/**
// # of times bloom filter has avoided file reads. * # of bytes of index block erased from cache
BLOOM_FILTER_USEFUL(20), */
BLOCK_CACHE_INDEX_BYTES_EVICT((byte) 0x8),
// # persistent cache hit
PERSISTENT_CACHE_HIT(21), /**
// # persistent cache miss * # of times cache miss when accessing filter block from block cache.
PERSISTENT_CACHE_MISS(22), */
BLOCK_CACHE_FILTER_MISS((byte) 0x9),
// # total simulation block cache hits
SIM_BLOCK_CACHE_HIT(23), /**
// # total simulation block cache misses * # of times cache hit when accessing filter block from block cache.
SIM_BLOCK_CACHE_MISS(24), */
BLOCK_CACHE_FILTER_HIT((byte) 0xA),
// # of memtable hits.
MEMTABLE_HIT(25), /**
// # of memtable misses. * # of filter blocks added to block cache.
MEMTABLE_MISS(26), */
BLOCK_CACHE_FILTER_ADD((byte) 0xB),
// # of Get() queries served by L0
GET_HIT_L0(27), /**
// # of Get() queries served by L1 * # of bytes of bloom filter blocks inserted into cache
GET_HIT_L1(28), */
// # of Get() queries served by L2 and up BLOCK_CACHE_FILTER_BYTES_INSERT((byte) 0xC),
GET_HIT_L2_AND_UP(29),
/**
/** * # of bytes of bloom filter block erased from cache
* COMPACTION_KEY_DROP_* count the reasons for key drop during compaction */
* There are 4 reasons currently. BLOCK_CACHE_FILTER_BYTES_EVICT((byte) 0xD),
*/
COMPACTION_KEY_DROP_NEWER_ENTRY(30), // key was written with a newer value. /**
// Also includes keys dropped for range del. * # of times cache miss when accessing data block from block cache.
COMPACTION_KEY_DROP_OBSOLETE(31), // The key is obsolete. */
COMPACTION_KEY_DROP_RANGE_DEL(32), // key was covered by a range tombstone. BLOCK_CACHE_DATA_MISS((byte) 0xE),
COMPACTION_KEY_DROP_USER(33), // user compaction function has dropped the key.
/**
COMPACTION_RANGE_DEL_DROP_OBSOLETE(34), // all keys in range were deleted. * # of times cache hit when accessing data block from block cache.
*/
// Number of keys written to the database via the Put and Write call's BLOCK_CACHE_DATA_HIT((byte) 0xF),
NUMBER_KEYS_WRITTEN(35),
// Number of Keys read, /**
NUMBER_KEYS_READ(36), * # of data blocks added to block cache.
// Number keys updated, if inplace update is enabled */
NUMBER_KEYS_UPDATED(37), BLOCK_CACHE_DATA_ADD((byte) 0x10),
// The number of uncompressed bytes issued by DB::Put(), DB::Delete(),
// DB::Merge(), and DB::Write(). /**
BYTES_WRITTEN(38), * # of bytes of data blocks inserted into cache
// The number of uncompressed bytes read from DB::Get(). It could be */
// either from memtables, cache, or table files. BLOCK_CACHE_DATA_BYTES_INSERT((byte) 0x11),
// For the number of logical bytes read from DB::MultiGet(),
// please use NUMBER_MULTIGET_BYTES_READ. /**
BYTES_READ(39), * # of bytes read from cache.
// The number of calls to seek/next/prev */
NUMBER_DB_SEEK(40), BLOCK_CACHE_BYTES_READ((byte) 0x12),
NUMBER_DB_NEXT(41),
NUMBER_DB_PREV(42), /**
// The number of calls to seek/next/prev that returned data * # of bytes written into cache.
NUMBER_DB_SEEK_FOUND(43), */
NUMBER_DB_NEXT_FOUND(44), BLOCK_CACHE_BYTES_WRITE((byte) 0x13),
NUMBER_DB_PREV_FOUND(45),
// The number of uncompressed bytes read from an iterator. /**
// Includes size of key and value. * # of times bloom filter has avoided file reads.
ITER_BYTES_READ(46), */
NO_FILE_CLOSES(47), BLOOM_FILTER_USEFUL((byte) 0x14),
NO_FILE_OPENS(48),
NO_FILE_ERRORS(49), /**
// DEPRECATED Time system had to wait to do LO-L1 compactions * # persistent cache hit
STALL_L0_SLOWDOWN_MICROS(50), */
// DEPRECATED Time system had to wait to move memtable to L1. PERSISTENT_CACHE_HIT((byte) 0x15),
STALL_MEMTABLE_COMPACTION_MICROS(51),
// DEPRECATED write throttle because of too many files in L0 /**
STALL_L0_NUM_FILES_MICROS(52), * # persistent cache miss
// Writer has to wait for compaction or flush to finish. */
STALL_MICROS(53), PERSISTENT_CACHE_MISS((byte) 0x16),
// The wait time for db mutex.
// Disabled by default. To enable it set stats level to kAll /**
DB_MUTEX_WAIT_MICROS(54), * # total simulation block cache hits
RATE_LIMIT_DELAY_MILLIS(55), */
NO_ITERATORS(56), // number of iterators currently open SIM_BLOCK_CACHE_HIT((byte) 0x17),
// Number of MultiGet calls, keys read, and bytes read /**
NUMBER_MULTIGET_CALLS(57), * # total simulation block cache misses
NUMBER_MULTIGET_KEYS_READ(58), */
NUMBER_MULTIGET_BYTES_READ(59), SIM_BLOCK_CACHE_MISS((byte) 0x18),
// Number of deletes records that were not required to be /**
// written to storage because key does not exist * # of memtable hits.
NUMBER_FILTERED_DELETES(60), */
NUMBER_MERGE_FAILURES(61), MEMTABLE_HIT((byte) 0x19),
// number of times bloom was checked before creating iterator on a /**
// file, and the number of times the check was useful in avoiding * # of memtable misses.
// iterator creation (and thus likely IOPs). */
BLOOM_FILTER_PREFIX_CHECKED(62), MEMTABLE_MISS((byte) 0x1A),
BLOOM_FILTER_PREFIX_USEFUL(63),
/**
// Number of times we had to reseek inside an iteration to skip * # of Get() queries served by L0
// over large number of keys with same userkey. */
NUMBER_OF_RESEEKS_IN_ITERATION(64), GET_HIT_L0((byte) 0x1B),
// Record the number of calls to GetUpadtesSince. Useful to keep track of /**
// transaction log iterator refreshes * # of Get() queries served by L1
GET_UPDATES_SINCE_CALLS(65), */
BLOCK_CACHE_COMPRESSED_MISS(66), // miss in the compressed block cache GET_HIT_L1((byte) 0x1C),
BLOCK_CACHE_COMPRESSED_HIT(67), // hit in the compressed block cache
// Number of blocks added to comopressed block cache /**
BLOCK_CACHE_COMPRESSED_ADD(68), * # of Get() queries served by L2 and up
// Number of failures when adding blocks to compressed block cache */
BLOCK_CACHE_COMPRESSED_ADD_FAILURES(69), GET_HIT_L2_AND_UP((byte) 0x1D),
WAL_FILE_SYNCED(70), // Number of times WAL sync is done
WAL_FILE_BYTES(71), // Number of bytes written to WAL /**
* COMPACTION_KEY_DROP_* count the reasons for key drop during compaction
// Writes can be processed by requesting thread or by the thread at the * There are 4 reasons currently.
// 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. * key was written with a newer value.
WRITE_WITH_WAL(75), // Number of Write calls that request WAL */
COMPACT_READ_BYTES(76), // Bytes read during compaction COMPACTION_KEY_DROP_NEWER_ENTRY((byte) 0x1E),
COMPACT_WRITE_BYTES(77), // Bytes written during compaction
FLUSH_WRITE_BYTES(78), // Bytes written during flush /**
* Also includes keys dropped for range del.
// Number of table's properties loaded directly from file, without creating * The key is obsolete.
// table reader object. */
NUMBER_DIRECT_LOAD_TABLE_PROPERTIES(79), COMPACTION_KEY_DROP_OBSOLETE((byte) 0x1F),
NUMBER_SUPERVERSION_ACQUIRES(80),
NUMBER_SUPERVERSION_RELEASES(81), /**
NUMBER_SUPERVERSION_CLEANUPS(82), * key was covered by a range tombstone.
*/
// # of compressions/decompressions executed COMPACTION_KEY_DROP_RANGE_DEL((byte) 0x20),
NUMBER_BLOCK_COMPRESSED(83),
NUMBER_BLOCK_DECOMPRESSED(84), /**
* User compaction function has dropped the key.
NUMBER_BLOCK_NOT_COMPRESSED(85), */
MERGE_OPERATION_TOTAL_TIME(86), COMPACTION_KEY_DROP_USER((byte) 0x21),
FILTER_OPERATION_TOTAL_TIME(87),
/**
// Row cache. * all keys in range were deleted.
ROW_CACHE_HIT(88), */
ROW_CACHE_MISS(89), COMPACTION_RANGE_DEL_DROP_OBSOLETE((byte) 0x22),
// Read amplification statistics. /**
// Read amplification can be calculated using this formula * Number of keys written to the database via the Put and Write call's.
// (READ_AMP_TOTAL_READ_BYTES / READ_AMP_ESTIMATE_USEFUL_BYTES) */
// NUMBER_KEYS_WRITTEN((byte) 0x23),
// 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 Keys read.
*/
// Number of refill intervals where rate limiter's bytes are fully consumed. NUMBER_KEYS_READ((byte) 0x24),
NUMBER_RATE_LIMITER_DRAINS(92);
/**
private final int value_; * Number keys updated, if inplace update is enabled
*/
private TickerType(int value) { NUMBER_KEYS_UPDATED((byte) 0x25),
value_ = value;
} /**
* The number of uncompressed bytes issued by DB::Put(), DB::Delete(),\
public int getValue() { * DB::Merge(), and DB::Write().
return value_; */
} 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 @Test
public void statistics() { public void statistics() {
try(final DBOptions options = new DBOptions()) { try(final DBOptions options = new DBOptions()) {
Statistics statistics = options.createStatistics(). final Statistics statistics = options.statistics();
statisticsPtr(); assertThat(statistics).isNull();
assertThat(statistics).isNotNull(); }
try(final DBOptions anotherOptions = new DBOptions()) { try(final Statistics statistics = new Statistics();
statistics = anotherOptions.statisticsPtr(); final DBOptions options = new DBOptions().setStatistics(statistics);
assertThat(statistics).isNotNull(); final Statistics stats = options.statistics()) {
} assertThat(stats).isNotNull();
} }
} }
} }

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

@ -26,27 +26,30 @@ public class StatisticsCollectorTest {
@Test @Test
public void statisticsCollector() public void statisticsCollector()
throws InterruptedException, RocksDBException { throws InterruptedException, RocksDBException {
try (final Options opt = new Options() try (final Statistics statistics = new Statistics();
.createStatistics() final Options opt = new Options()
.setStatistics(statistics)
.setCreateIfMissing(true); .setCreateIfMissing(true);
final RocksDB db = RocksDB.open(opt, final RocksDB db = RocksDB.open(opt,
dbFolder.getRoot().getAbsolutePath())) { dbFolder.getRoot().getAbsolutePath())) {
final Statistics stats = opt.statisticsPtr();
final StatsCallbackMock callback = new StatsCallbackMock(); try(final Statistics stats = opt.statistics()) {
final StatsCollectorInput statsInput =
new StatsCollectorInput(stats, callback);
final StatisticsCollector statsCollector = new StatisticsCollector( final StatsCallbackMock callback = new StatsCallbackMock();
Collections.singletonList(statsInput), 100); final StatsCollectorInput statsInput =
statsCollector.start(); new StatsCollectorInput(stats, callback);
Thread.sleep(1000); final StatisticsCollector statsCollector = new StatisticsCollector(
Collections.singletonList(statsInput), 100);
statsCollector.start();
assertThat(callback.tickerCallbackCount).isGreaterThan(0); Thread.sleep(1000);
assertThat(callback.histCallbackCount).isGreaterThan(0);
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/snapshot.cc \
java/rocksjni/sst_file_writerjni.cc \ java/rocksjni/sst_file_writerjni.cc \
java/rocksjni/statistics.cc \ java/rocksjni/statistics.cc \
java/rocksjni/statisticsjni.cc \
java/rocksjni/table.cc \ java/rocksjni/table.cc \
java/rocksjni/transaction_log.cc \ java/rocksjni/transaction_log.cc \
java/rocksjni/ttl.cc \ java/rocksjni/ttl.cc \

Loading…
Cancel
Save