From 000bf0af380e2d35974fa9c04599d34306831330 Mon Sep 17 00:00:00 2001 From: Adam Retter Date: Tue, 11 Jul 2017 23:19:53 -0700 Subject: [PATCH] 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 --- java/CMakeLists.txt | 1 + java/Makefile | 15 +- java/rocksjni/options.cc | 66 +- java/rocksjni/portal.h | 597 +++++++++++++++ java/rocksjni/statistics.cc | 220 +++++- java/rocksjni/statisticsjni.cc | 33 + java/rocksjni/statisticsjni.h | 33 + java/src/main/java/org/rocksdb/DBOptions.java | 22 +- .../java/org/rocksdb/DBOptionsInterface.java | 13 +- .../main/java/org/rocksdb/HistogramType.java | 130 ++-- .../main/java/org/rocksdb/InfoLogLevel.java | 2 +- java/src/main/java/org/rocksdb/Options.java | 22 +- .../src/main/java/org/rocksdb/Statistics.java | 140 +++- .../java/org/rocksdb/StatisticsCollector.java | 26 +- .../src/main/java/org/rocksdb/StatsLevel.java | 65 ++ .../src/main/java/org/rocksdb/TickerType.java | 678 ++++++++++++------ .../test/java/org/rocksdb/DBOptionsTest.java | 14 +- .../test/java/org/rocksdb/OptionsTest.java | 17 +- .../org/rocksdb/StatisticsCollectorTest.java | 29 +- .../test/java/org/rocksdb/StatisticsTest.java | 160 +++++ src.mk | 1 + 21 files changed, 1900 insertions(+), 384 deletions(-) create mode 100644 java/rocksjni/statisticsjni.cc create mode 100644 java/rocksjni/statisticsjni.h create mode 100644 java/src/main/java/org/rocksdb/StatsLevel.java create mode 100644 java/src/test/java/org/rocksdb/StatisticsTest.java diff --git a/java/CMakeLists.txt b/java/CMakeLists.txt index fae91f93c..b77b4213c 100644 --- a/java/CMakeLists.txt +++ b/java/CMakeLists.txt @@ -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 diff --git a/java/Makefile b/java/Makefile index c90c261f4..7e1597a2e 100644 --- a/java/Makefile +++ b/java/Makefile @@ -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 diff --git a/java/rocksjni/options.cc b/java/rocksjni/options.cc index 744b9e6f6..295aa6493 100644 --- a/java/rocksjni/options.cc +++ b/java/rocksjni/options.cc @@ -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(jOptHandle)->statistics = - rocksdb::CreateDBStatistics(); +void Java_org_rocksdb_Options_setStatistics( + JNIEnv* env, jobject jobj, jlong jhandle, jlong jstatistics_handle) { + auto* opt = reinterpret_cast(jhandle); + auto* pSptr = + reinterpret_cast*>( + 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(jOptHandle)->statistics.get(); - return reinterpret_cast(st); +jlong Java_org_rocksdb_Options_statistics( + JNIEnv* env, jobject jobj, jlong jhandle) { + auto* opt = reinterpret_cast(jhandle); + std::shared_ptr sptr = opt->statistics; + if (sptr == nullptr) { + return 0; + } else { + std::shared_ptr* pSptr = + new std::shared_ptr(sptr); + return reinterpret_cast(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(jOptHandle)->statistics = - rocksdb::CreateDBStatistics(); +void Java_org_rocksdb_DBOptions_setStatistics( + JNIEnv* env, jobject jobj, jlong jhandle, jlong jstatistics_handle) { + auto* opt = reinterpret_cast(jhandle); + auto* pSptr = + reinterpret_cast*>( + 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(jOptHandle)-> - statistics.get(); - return reinterpret_cast(st); +jlong Java_org_rocksdb_DBOptions_statistics( + JNIEnv* env, jobject jobj, jlong jhandle) { + auto* opt = reinterpret_cast(jhandle); + std::shared_ptr sptr = opt->statistics; + if (sptr == nullptr) { + return 0; + } else { + std::shared_ptr* pSptr = + new std::shared_ptr(sptr); + return reinterpret_cast(pSptr); + } } /* diff --git a/java/rocksjni/portal.h b/java/rocksjni/portal.h index aad26e570..91f6fef79 100644 --- a/java/rocksjni/portal.h +++ b/java/rocksjni/portal.h @@ -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: diff --git a/java/rocksjni/statistics.cc b/java/rocksjni/statistics.cc index 6a30fa043..4b6877806 100644 --- a/java/rocksjni/statistics.cc +++ b/java/rocksjni/statistics.cc @@ -6,39 +6,178 @@ // This file implements the "bridge" between Java and C++ and enables // calling c++ rocksdb::Statistics methods from Java side. -#include -#include #include +#include +#include #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(handle); - assert(st != nullptr); - return st->getTickerCount(static_cast(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(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* pSptr_other_statistics = nullptr; + if (jother_statistics_handle > 0) { + pSptr_other_statistics = + reinterpret_cast*>( + jother_statistics_handle); + } + + std::set 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 sptr_other_statistics = nullptr; + if (pSptr_other_statistics != nullptr) { + sptr_other_statistics = *pSptr_other_statistics; + } + + auto* pSptr_statistics = new std::shared_ptr( + new rocksdb::StatisticsJni(sptr_other_statistics, histograms)); - rocksdb::HistogramData data; - st->histogramData(static_cast(histogramType), - &data); + return reinterpret_cast(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*>(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*>(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*>(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*>(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*>(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*>(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(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*>(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*>(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*>(jhandle); + assert(pSptr_statistics != nullptr); + auto str = pSptr_statistics->get()->ToString(); + return env->NewStringUTF(str.c_str()); +} diff --git a/java/rocksjni/statisticsjni.cc b/java/rocksjni/statisticsjni.cc new file mode 100644 index 000000000..dc1d8f9f8 --- /dev/null +++ b/java/rocksjni/statisticsjni.cc @@ -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 stats) + : StatisticsImpl(stats, false), m_ignore_histograms() { + } + + StatisticsJni::StatisticsJni(std::shared_ptr stats, + const std::set 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; + } +}; \ No newline at end of file diff --git a/java/rocksjni/statisticsjni.h b/java/rocksjni/statisticsjni.h new file mode 100644 index 000000000..d7c3ef3aa --- /dev/null +++ b/java/rocksjni/statisticsjni.h @@ -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 +#include +#include +#include "rocksdb/statistics.h" +#include "monitoring/statistics.h" + +namespace rocksdb { + + class StatisticsJni : public StatisticsImpl { + public: + StatisticsJni(std::shared_ptr stats); + StatisticsJni(std::shared_ptr stats, + const std::set ignore_histograms); + virtual bool HistEnabledForType(uint32_t type) const override; + + private: + const std::set m_ignore_histograms; + }; + +} // namespace rocksdb + +#endif // JAVA_ROCKSJNI_STATISTICSJNI_H_ \ No newline at end of file diff --git a/java/src/main/java/org/rocksdb/DBOptions.java b/java/src/main/java/org/rocksdb/DBOptions.java index c29ca9cb8..bc8cfa753 100644 --- a/java/src/main/java/org/rocksdb/DBOptions.java +++ b/java/src/main/java/org/rocksdb/DBOptions.java @@ -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, diff --git a/java/src/main/java/org/rocksdb/DBOptionsInterface.java b/java/src/main/java/org/rocksdb/DBOptionsInterface.java index 72dd59340..aeee6414a 100644 --- a/java/src/main/java/org/rocksdb/DBOptionsInterface.java +++ b/java/src/main/java/org/rocksdb/DBOptionsInterface.java @@ -265,23 +265,22 @@ public interface DBOptionsInterface { long maxTotalWalSize(); /** - *

Creates statistics object which collects metrics about database operations. + *

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.

* * @return the instance of the current object. * @see RocksDB#open(org.rocksdb.Options, String) */ - T createStatistics(); + T setStatistics(final Statistics statistics); /** - *

Returns statistics object. Calls {@link #createStatistics()} if - * C++ returns {@code nullptr} for statistics.

+ *

Returns statistics object.

* - * @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(); /** *

If true, then every store to stable storage will issue a fsync.

diff --git a/java/src/main/java/org/rocksdb/HistogramType.java b/java/src/main/java/org/rocksdb/HistogramType.java index 78e98cfbe..bd001ed02 100644 --- a/java/src/main/java/org/rocksdb/HistogramType.java +++ b/java/src/main/java/org/rocksdb/HistogramType.java @@ -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; } } diff --git a/java/src/main/java/org/rocksdb/InfoLogLevel.java b/java/src/main/java/org/rocksdb/InfoLogLevel.java index 35a206250..2c97991b5 100644 --- a/java/src/main/java/org/rocksdb/InfoLogLevel.java +++ b/java/src/main/java/org/rocksdb/InfoLogLevel.java @@ -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. */ diff --git a/java/src/main/java/org/rocksdb/Options.java b/java/src/main/java/org/rocksdb/Options.java index f11ad392a..ad6b7ae37 100644 --- a/java/src/main/java/org/rocksdb/Options.java +++ b/java/src/main/java/org/rocksdb/Options.java @@ -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, diff --git a/java/src/main/java/org/rocksdb/Statistics.java b/java/src/main/java/org/rocksdb/Statistics.java index 858637763..96e9b5d23 100644 --- a/java/src/main/java/org/rocksdb/Statistics.java +++ b/java/src/main/java/org/rocksdb/Statistics.java @@ -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 ignoreHistograms) { + super(newStatistics(toArrayValues(ignoreHistograms))); + } + + public Statistics(final EnumSet 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 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); } diff --git a/java/src/main/java/org/rocksdb/StatisticsCollector.java b/java/src/main/java/org/rocksdb/StatisticsCollector.java index 246826d32..8ebcb4dbc 100644 --- a/java/src/main/java/org/rocksdb/StatisticsCollector.java +++ b/java/src/main/java/org/rocksdb/StatisticsCollector.java @@ -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); } } diff --git a/java/src/main/java/org/rocksdb/StatsLevel.java b/java/src/main/java/org/rocksdb/StatsLevel.java new file mode 100644 index 000000000..023d4e1a2 --- /dev/null +++ b/java/src/main/java/org/rocksdb/StatsLevel.java @@ -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; + } + + /** + *

Returns the byte value of the enumerations value.

+ * + * @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."); + } +} diff --git a/java/src/main/java/org/rocksdb/TickerType.java b/java/src/main/java/org/rocksdb/TickerType.java index 7528e57d9..69b50399b 100644 --- a/java/src/main/java/org/rocksdb/TickerType.java +++ b/java/src/main/java/org/rocksdb/TickerType.java @@ -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; + } } diff --git a/java/src/test/java/org/rocksdb/DBOptionsTest.java b/java/src/test/java/org/rocksdb/DBOptionsTest.java index 2bbaf1465..ba3e9e41c 100644 --- a/java/src/test/java/org/rocksdb/DBOptionsTest.java +++ b/java/src/test/java/org/rocksdb/DBOptionsTest.java @@ -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(); } } } diff --git a/java/src/test/java/org/rocksdb/OptionsTest.java b/java/src/test/java/org/rocksdb/OptionsTest.java index 8b46ea6b7..71f6ee7df 100644 --- a/java/src/test/java/org/rocksdb/OptionsTest.java +++ b/java/src/test/java/org/rocksdb/OptionsTest.java @@ -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(); } } diff --git a/java/src/test/java/org/rocksdb/StatisticsCollectorTest.java b/java/src/test/java/org/rocksdb/StatisticsCollectorTest.java index 9f014d1d3..565449d76 100644 --- a/java/src/test/java/org/rocksdb/StatisticsCollectorTest.java +++ b/java/src/test/java/org/rocksdb/StatisticsCollectorTest.java @@ -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); + } } } } diff --git a/java/src/test/java/org/rocksdb/StatisticsTest.java b/java/src/test/java/org/rocksdb/StatisticsTest.java new file mode 100644 index 000000000..6b1d0f16c --- /dev/null +++ b/java/src/test/java/org/rocksdb/StatisticsTest.java @@ -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(); + } + } +} diff --git a/src.mk b/src.mk index 591f4a427..8250947f5 100644 --- a/src.mk +++ b/src.mk @@ -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 \