Current section

Files

Jump to
rocksdb test blob_statistics.erl
Raw

test/blob_statistics.erl

-module(blob_statistics).
-export([ticker_test/0, histogram_test/0]).
-define(rm_rf(Dir), rocksdb_test_util:rm_rf(Dir)).
%% Value size larger than min_blob_size to ensure blobs are written
-define(VALUE_SIZE, 100).
ticker_test() ->
?rm_rf("test_blob_stats"),
{ok, Stats} = rocksdb:new_statistics(),
%% Create a blob cache for cache statistics
{ok, BlobCache} = rocksdb:new_cache(lru, 1048576),
{ok, Db} =
rocksdb:open(
"test_blob_stats",
[{create_if_missing, true}
,{enable_blob_files, true}
,{min_blob_size, 0} %% All values go to blob files
,{blob_cache, BlobCache}
,{prepopulate_blob_cache, flush_only} %% Populate cache on flush
,{statistics, Stats}]
),
try
%% Check initial blob file bytes written is 0
{ok, 0} = rocksdb:statistics_ticker(Stats, blob_db_blob_file_bytes_written),
%% Write some data (large enough to be stored as blobs)
Value1 = list_to_binary(lists:duplicate(?VALUE_SIZE, $a)),
Value2 = list_to_binary(lists:duplicate(?VALUE_SIZE, $b)),
ok = rocksdb:put(Db, <<"key1">>, Value1, []),
ok = rocksdb:put(Db, <<"key2">>, Value2, []),
ok = rocksdb:flush(Db, []),
%% Check blob file bytes written increased
{ok, BlobBytesWritten} = rocksdb:statistics_ticker(Stats, blob_db_blob_file_bytes_written),
true = BlobBytesWritten > 0,
%% With prepopulate_blob_cache=flush_only, blobs should be in cache after flush
{ok, CacheAdd} = rocksdb:statistics_ticker(Stats, blob_db_cache_add),
true = CacheAdd >= 2, %% 2 blobs added to cache
%% Read data - should hit cache
{ok, Value1} = rocksdb:get(Db, <<"key1">>, []),
{ok, Value2} = rocksdb:get(Db, <<"key2">>, []),
%% Check cache hit count
{ok, CacheHit} = rocksdb:statistics_ticker(Stats, blob_db_cache_hit),
true = CacheHit >= 2,
%% Check cache bytes read
{ok, CacheBytesRead} = rocksdb:statistics_ticker(Stats, blob_db_cache_bytes_read),
true = CacheBytesRead > 0,
%% Check cache miss should be 0 or minimal (since we prepopulated)
{ok, CacheMiss} = rocksdb:statistics_ticker(Stats, blob_db_cache_miss),
true = CacheMiss =:= 0,
%% Test other tickers can be read (they may be 0 for integrated BlobDB)
{ok, _BlobFileBytesRead} = rocksdb:statistics_ticker(Stats, blob_db_blob_file_bytes_read),
{ok, _BlobFileSynced} = rocksdb:statistics_ticker(Stats, blob_db_blob_file_synced),
%% GC tickers (will be 0 since no GC occurred)
{ok, 0} = rocksdb:statistics_ticker(Stats, blob_db_gc_num_files),
{ok, 0} = rocksdb:statistics_ticker(Stats, blob_db_gc_num_new_files),
{ok, 0} = rocksdb:statistics_ticker(Stats, blob_db_gc_failures),
{ok, 0} = rocksdb:statistics_ticker(Stats, blob_db_gc_num_keys_relocated),
{ok, 0} = rocksdb:statistics_ticker(Stats, blob_db_gc_bytes_relocated),
%% Test cache failure ticker (should be 0)
{ok, 0} = rocksdb:statistics_ticker(Stats, blob_db_cache_add_failures),
%% Legacy BlobDB tickers (not used by integrated BlobDB, but should return 0)
{ok, 0} = rocksdb:statistics_ticker(Stats, blob_db_num_put),
{ok, 0} = rocksdb:statistics_ticker(Stats, blob_db_num_get),
{ok, 0} = rocksdb:statistics_ticker(Stats, blob_db_num_write),
{ok, 0} = rocksdb:statistics_ticker(Stats, blob_db_num_multiget),
{ok, 0} = rocksdb:statistics_ticker(Stats, blob_db_num_seek),
{ok, 0} = rocksdb:statistics_ticker(Stats, blob_db_num_next),
{ok, 0} = rocksdb:statistics_ticker(Stats, blob_db_num_prev),
{ok, 0} = rocksdb:statistics_ticker(Stats, blob_db_num_keys_written),
{ok, 0} = rocksdb:statistics_ticker(Stats, blob_db_num_keys_read),
{ok, 0} = rocksdb:statistics_ticker(Stats, blob_db_bytes_written),
{ok, 0} = rocksdb:statistics_ticker(Stats, blob_db_bytes_read),
{ok, 0} = rocksdb:statistics_ticker(Stats, blob_db_write_inlined),
{ok, 0} = rocksdb:statistics_ticker(Stats, blob_db_write_inlined_ttl),
{ok, 0} = rocksdb:statistics_ticker(Stats, blob_db_write_blob),
{ok, 0} = rocksdb:statistics_ticker(Stats, blob_db_write_blob_ttl),
{ok, 0} = rocksdb:statistics_ticker(Stats, blob_db_blob_index_expired_count),
{ok, 0} = rocksdb:statistics_ticker(Stats, blob_db_blob_index_expired_size),
{ok, 0} = rocksdb:statistics_ticker(Stats, blob_db_blob_index_evicted_count),
{ok, 0} = rocksdb:statistics_ticker(Stats, blob_db_blob_index_evicted_size),
{ok, 0} = rocksdb:statistics_ticker(Stats, blob_db_fifo_num_files_evicted),
{ok, 0} = rocksdb:statistics_ticker(Stats, blob_db_fifo_num_keys_evicted),
{ok, 0} = rocksdb:statistics_ticker(Stats, blob_db_fifo_bytes_evicted)
after
ok = rocksdb:close(Db),
ok = rocksdb:release_statistics(Stats),
ok = rocksdb:release_cache(BlobCache),
?rm_rf("test_blob_stats")
end,
ok.
histogram_test() ->
?rm_rf("test_blob_hist"),
{ok, Stats} = rocksdb:new_statistics(),
{ok, Db} =
rocksdb:open(
"test_blob_hist",
[{create_if_missing, true}
,{enable_blob_files, true}
,{min_blob_size, 0}
,{statistics, Stats}]
),
try
%% Write some data to generate blob file writes
Value = list_to_binary(lists:duplicate(?VALUE_SIZE, $a)),
ok = rocksdb:put(Db, <<"key1">>, Value, []),
ok = rocksdb:put(Db, <<"key2">>, Value, []),
ok = rocksdb:flush(Db, []),
%% Test blob file write histogram (used by integrated BlobDB)
{ok, WriteHist} = rocksdb:statistics_histogram(Stats, blob_db_blob_file_write_micros),
true = is_map(WriteHist),
#{median := Median, percentile95 := P95, percentile99 := P99,
average := Avg, standard_deviation := StdDev,
max := Max, count := Count, sum := Sum} = WriteHist,
true = is_float(Median),
true = is_float(P95),
true = is_float(P99),
true = is_float(Avg),
true = is_float(StdDev),
true = is_float(Max),
true = is_integer(Count),
true = is_integer(Sum),
%% Read data to generate read histograms
{ok, Value} = rocksdb:get(Db, <<"key1">>, []),
%% Test blob file read histogram
{ok, ReadHist} = rocksdb:statistics_histogram(Stats, blob_db_blob_file_read_micros),
true = is_map(ReadHist),
#{count := ReadCount} = ReadHist,
true = is_integer(ReadCount),
%% Test blob file sync histogram
{ok, SyncHist} = rocksdb:statistics_histogram(Stats, blob_db_blob_file_sync_micros),
true = is_map(SyncHist),
%% Test compression/decompression histograms (may have 0 count if no compression)
{ok, CompHist} = rocksdb:statistics_histogram(Stats, blob_db_compression_micros),
true = is_map(CompHist),
{ok, DecompHist} = rocksdb:statistics_histogram(Stats, blob_db_decompression_micros),
true = is_map(DecompHist),
%% Test legacy BlobDB histograms (should return maps with 0 counts)
{ok, KeySizeHist} = rocksdb:statistics_histogram(Stats, blob_db_key_size),
true = is_map(KeySizeHist),
#{count := 0} = KeySizeHist,
{ok, ValueSizeHist} = rocksdb:statistics_histogram(Stats, blob_db_value_size),
true = is_map(ValueSizeHist),
{ok, WriteMicrosHist} = rocksdb:statistics_histogram(Stats, blob_db_write_micros),
true = is_map(WriteMicrosHist),
{ok, GetMicrosHist} = rocksdb:statistics_histogram(Stats, blob_db_get_micros),
true = is_map(GetMicrosHist),
{ok, MultigetMicrosHist} = rocksdb:statistics_histogram(Stats, blob_db_multiget_micros),
true = is_map(MultigetMicrosHist),
{ok, SeekMicrosHist} = rocksdb:statistics_histogram(Stats, blob_db_seek_micros),
true = is_map(SeekMicrosHist),
{ok, NextMicrosHist} = rocksdb:statistics_histogram(Stats, blob_db_next_micros),
true = is_map(NextMicrosHist),
{ok, PrevMicrosHist} = rocksdb:statistics_histogram(Stats, blob_db_prev_micros),
true = is_map(PrevMicrosHist)
after
ok = rocksdb:close(Db),
ok = rocksdb:release_statistics(Stats),
?rm_rf("test_blob_hist")
end,
ok.