Commit bf229ed5 authored by Yun Tang's avatar Yun Tang
Browse files

[FLINK-19710] Revert implementation of PerfContext back to __thread to avoid performance regression

parent c9c5eb54
...@@ -690,89 +690,6 @@ TEST_F(PerfContextTest, MergeOperatorTime) { ...@@ -690,89 +690,6 @@ TEST_F(PerfContextTest, MergeOperatorTime) {
delete db; delete db;
} }
TEST_F(PerfContextTest, CopyAndMove) {
// Assignment operator
{
get_perf_context()->Reset();
get_perf_context()->EnablePerLevelPerfContext();
PERF_COUNTER_BY_LEVEL_ADD(bloom_filter_useful, 1, 5);
ASSERT_EQ(
1,
(*(get_perf_context()->level_to_perf_context))[5].bloom_filter_useful);
PerfContext perf_context_assign;
perf_context_assign = *get_perf_context();
ASSERT_EQ(
1,
(*(perf_context_assign.level_to_perf_context))[5].bloom_filter_useful);
get_perf_context()->ClearPerLevelPerfContext();
get_perf_context()->Reset();
ASSERT_EQ(
1,
(*(perf_context_assign.level_to_perf_context))[5].bloom_filter_useful);
perf_context_assign.ClearPerLevelPerfContext();
perf_context_assign.Reset();
}
// Copy constructor
{
get_perf_context()->Reset();
get_perf_context()->EnablePerLevelPerfContext();
PERF_COUNTER_BY_LEVEL_ADD(bloom_filter_useful, 1, 5);
ASSERT_EQ(
1,
(*(get_perf_context()->level_to_perf_context))[5].bloom_filter_useful);
PerfContext perf_context_copy(*get_perf_context());
ASSERT_EQ(
1, (*(perf_context_copy.level_to_perf_context))[5].bloom_filter_useful);
get_perf_context()->ClearPerLevelPerfContext();
get_perf_context()->Reset();
ASSERT_EQ(
1, (*(perf_context_copy.level_to_perf_context))[5].bloom_filter_useful);
perf_context_copy.ClearPerLevelPerfContext();
perf_context_copy.Reset();
}
// Move constructor
{
get_perf_context()->Reset();
get_perf_context()->EnablePerLevelPerfContext();
PERF_COUNTER_BY_LEVEL_ADD(bloom_filter_useful, 1, 5);
ASSERT_EQ(
1,
(*(get_perf_context()->level_to_perf_context))[5].bloom_filter_useful);
PerfContext perf_context_move = std::move(*get_perf_context());
ASSERT_EQ(
1, (*(perf_context_move.level_to_perf_context))[5].bloom_filter_useful);
get_perf_context()->ClearPerLevelPerfContext();
get_perf_context()->Reset();
ASSERT_EQ(
1, (*(perf_context_move.level_to_perf_context))[5].bloom_filter_useful);
perf_context_move.ClearPerLevelPerfContext();
perf_context_move.Reset();
}
}
TEST_F(PerfContextTest, PerfContextDisableEnable) {
get_perf_context()->Reset();
get_perf_context()->EnablePerLevelPerfContext();
PERF_COUNTER_BY_LEVEL_ADD(bloom_filter_full_positive, 1, 0);
get_perf_context()->DisablePerLevelPerfContext();
PERF_COUNTER_BY_LEVEL_ADD(bloom_filter_useful, 1, 5);
get_perf_context()->EnablePerLevelPerfContext();
PERF_COUNTER_BY_LEVEL_ADD(block_cache_hit_count, 1, 0);
get_perf_context()->DisablePerLevelPerfContext();
PerfContext perf_context_copy(*get_perf_context());
ASSERT_EQ(1, (*(perf_context_copy.level_to_perf_context))[0]
.bloom_filter_full_positive);
// this was set when per level perf context is disabled, should not be copied
ASSERT_NE(
1, (*(perf_context_copy.level_to_perf_context))[5].bloom_filter_useful);
ASSERT_EQ(
1, (*(perf_context_copy.level_to_perf_context))[0].block_cache_hit_count);
perf_context_copy.ClearPerLevelPerfContext();
perf_context_copy.Reset();
get_perf_context()->ClearPerLevelPerfContext();
get_perf_context()->Reset();
}
TEST_F(PerfContextTest, PerfContextByLevelGetSet) { TEST_F(PerfContextTest, PerfContextByLevelGetSet) {
get_perf_context()->Reset(); get_perf_context()->Reset();
get_perf_context()->EnablePerLevelPerfContext(); get_perf_context()->EnablePerLevelPerfContext();
......
...@@ -42,13 +42,6 @@ struct PerfContextByLevel { ...@@ -42,13 +42,6 @@ struct PerfContextByLevel {
}; };
struct PerfContext { struct PerfContext {
~PerfContext();
PerfContext() {}
PerfContext(const PerfContext&);
PerfContext& operator=(const PerfContext&);
PerfContext(PerfContext&&) noexcept;
void Reset(); // reset all performance counters to zero void Reset(); // reset all performance counters to zero
...@@ -60,26 +53,23 @@ struct PerfContext { ...@@ -60,26 +53,23 @@ struct PerfContext {
// temporarily disable per level perf contxt by setting the flag to false // temporarily disable per level perf contxt by setting the flag to false
void DisablePerLevelPerfContext(); void DisablePerLevelPerfContext();
// free the space for PerfContextByLevel, also disable per level perf context uint64_t user_key_comparison_count{}; // total number of user key comparisons
void ClearPerLevelPerfContext(); uint64_t block_cache_hit_count{}; // total number of block cache hits
uint64_t block_read_count{}; // total number of block reads (with IO)
uint64_t user_key_comparison_count; // total number of user key comparisons uint64_t block_read_byte{}; // total number of bytes from block reads
uint64_t block_cache_hit_count; // total number of block cache hits uint64_t block_read_time{}; // total nanos spent on block reads
uint64_t block_read_count; // total number of block reads (with IO) uint64_t block_cache_index_hit_count{}; // total number of index block hits
uint64_t block_read_byte; // total number of bytes from block reads uint64_t index_block_read_count{}; // total number of index block reads
uint64_t block_read_time; // total nanos spent on block reads uint64_t block_cache_filter_hit_count{}; // total number of filter block hits
uint64_t block_cache_index_hit_count; // total number of index block hits uint64_t filter_block_read_count{}; // total number of filter block reads
uint64_t index_block_read_count; // total number of index block reads uint64_t compression_dict_block_read_count{}; // total number of compression
uint64_t block_cache_filter_hit_count; // total number of filter block hits // dictionary block reads
uint64_t filter_block_read_count; // total number of filter block reads uint64_t block_checksum_time{}; // total nanos spent on block checksum
uint64_t compression_dict_block_read_count; // total number of compression uint64_t block_decompress_time{}; // total nanos spent on block decompression
// dictionary block reads
uint64_t block_checksum_time; // total nanos spent on block checksum uint64_t get_read_bytes{}; // bytes for vals returned by Get
uint64_t block_decompress_time; // total nanos spent on block decompression uint64_t multiget_read_bytes{}; // bytes for vals returned by MultiGet
uint64_t iter_read_bytes{}; // bytes for keys/vals decoded by iterator
uint64_t get_read_bytes; // bytes for vals returned by Get
uint64_t multiget_read_bytes; // bytes for vals returned by MultiGet
uint64_t iter_read_bytes; // bytes for keys/vals decoded by iterator
// total number of internal keys skipped over during iteration. // total number of internal keys skipped over during iteration.
// There are several reasons for it: // There are several reasons for it:
...@@ -98,7 +88,7 @@ struct PerfContext { ...@@ -98,7 +88,7 @@ struct PerfContext {
// 4. symmetric cases for Prev() and SeekToLast() // 4. symmetric cases for Prev() and SeekToLast()
// internal_recent_skipped_count is not included in this counter. // internal_recent_skipped_count is not included in this counter.
// //
uint64_t internal_key_skipped_count; uint64_t internal_key_skipped_count{};
// Total number of deletes and single deletes skipped over during iteration // Total number of deletes and single deletes skipped over during iteration
// When calling Next(), Seek() or SeekToFirst(), after previous position // When calling Next(), Seek() or SeekToFirst(), after previous position
// before calling Next(), the seek key in Seek() or the beginning for // before calling Next(), the seek key in Seek() or the beginning for
...@@ -106,125 +96,126 @@ struct PerfContext { ...@@ -106,125 +96,126 @@ struct PerfContext {
// key. Every deleted key is counted once. We don't recount here if there are // key. Every deleted key is counted once. We don't recount here if there are
// still older updates invalidated by the tombstones. // still older updates invalidated by the tombstones.
// //
uint64_t internal_delete_skipped_count; uint64_t internal_delete_skipped_count{};
// How many times iterators skipped over internal keys that are more recent // How many times iterators skipped over internal keys that are more recent
// than the snapshot that iterator is using. // than the snapshot that iterator is using.
// //
uint64_t internal_recent_skipped_count; uint64_t internal_recent_skipped_count{};
// How many values were fed into merge operator by iterators. // How many values were fed into merge operator by iterators.
// //
uint64_t internal_merge_count; uint64_t internal_merge_count{};
uint64_t get_snapshot_time; // total nanos spent on getting snapshot uint64_t get_snapshot_time{}; // total nanos spent on getting snapshot
uint64_t get_from_memtable_time; // total nanos spent on querying memtables uint64_t get_from_memtable_time{}; // total nanos spent on querying memtables
uint64_t get_from_memtable_count; // number of mem tables queried uint64_t get_from_memtable_count{}; // number of mem tables queried
// total nanos spent after Get() finds a key // total nanos spent after Get() finds a key
uint64_t get_post_process_time; uint64_t get_post_process_time{};
uint64_t get_from_output_files_time; // total nanos reading from output files uint64_t
get_from_output_files_time{}; // total nanos reading from output files
// total nanos spent on seeking memtable // total nanos spent on seeking memtable
uint64_t seek_on_memtable_time; uint64_t seek_on_memtable_time{};
// number of seeks issued on memtable // number of seeks issued on memtable
// (including SeekForPrev but not SeekToFirst and SeekToLast) // (including SeekForPrev but not SeekToFirst and SeekToLast)
uint64_t seek_on_memtable_count; uint64_t seek_on_memtable_count{};
// number of Next()s issued on memtable // number of Next()s issued on memtable
uint64_t next_on_memtable_count; uint64_t next_on_memtable_count{};
// number of Prev()s issued on memtable // number of Prev()s issued on memtable
uint64_t prev_on_memtable_count; uint64_t prev_on_memtable_count{};
// total nanos spent on seeking child iters // total nanos spent on seeking child iters
uint64_t seek_child_seek_time; uint64_t seek_child_seek_time{};
// number of seek issued in child iterators // number of seek issued in child iterators
uint64_t seek_child_seek_count; uint64_t seek_child_seek_count{};
uint64_t seek_min_heap_time; // total nanos spent on the merge min heap uint64_t seek_min_heap_time{}; // total nanos spent on the merge min heap
uint64_t seek_max_heap_time; // total nanos spent on the merge max heap uint64_t seek_max_heap_time{}; // total nanos spent on the merge max heap
// total nanos spent on seeking the internal entries // total nanos spent on seeking the internal entries
uint64_t seek_internal_seek_time; uint64_t seek_internal_seek_time{};
// total nanos spent on iterating internal entries to find the next user entry // total nanos spent on iterating internal entries to find the next user entry
uint64_t find_next_user_entry_time; uint64_t find_next_user_entry_time{};
// This group of stats provide a breakdown of time spent by Write(). // This group of stats provide a breakdown of time spent by Write().
// May be inaccurate when 2PC, two_write_queues or enable_pipelined_write // May be inaccurate when 2PC, two_write_queues or enable_pipelined_write
// are enabled. // are enabled.
// //
// total nanos spent on writing to WAL // total nanos spent on writing to WAL
uint64_t write_wal_time; uint64_t write_wal_time{};
// total nanos spent on writing to mem tables // total nanos spent on writing to mem tables
uint64_t write_memtable_time; uint64_t write_memtable_time{};
// total nanos spent on delaying or throttling write // total nanos spent on delaying or throttling write
uint64_t write_delay_time; uint64_t write_delay_time{};
// total nanos spent on switching memtable/wal and scheduling // total nanos spent on switching memtable/wal and scheduling
// flushes/compactions. // flushes/compactions.
uint64_t write_scheduling_flushes_compactions_time; uint64_t write_scheduling_flushes_compactions_time{};
// total nanos spent on writing a record, excluding the above four things // total nanos spent on writing a record, excluding the above four things
uint64_t write_pre_and_post_process_time; uint64_t write_pre_and_post_process_time{};
// time spent waiting for other threads of the batch group // time spent waiting for other threads of the batch group
uint64_t write_thread_wait_nanos; uint64_t write_thread_wait_nanos{};
// time spent on acquiring DB mutex. // time spent on acquiring DB mutex.
uint64_t db_mutex_lock_nanos; uint64_t db_mutex_lock_nanos{};
// Time spent on waiting with a condition variable created with DB mutex. // Time spent on waiting with a condition variable created with DB mutex.
uint64_t db_condition_wait_nanos; uint64_t db_condition_wait_nanos{};
// Time spent on merge operator. // Time spent on merge operator.
uint64_t merge_operator_time_nanos; uint64_t merge_operator_time_nanos{};
// Time spent on reading index block from block cache or SST file // Time spent on reading index block from block cache or SST file
uint64_t read_index_block_nanos; uint64_t read_index_block_nanos{};
// Time spent on reading filter block from block cache or SST file // Time spent on reading filter block from block cache or SST file
uint64_t read_filter_block_nanos; uint64_t read_filter_block_nanos{};
// Time spent on creating data block iterator // Time spent on creating data block iterator
uint64_t new_table_block_iter_nanos; uint64_t new_table_block_iter_nanos{};
// Time spent on creating a iterator of an SST file. // Time spent on creating a iterator of an SST file.
uint64_t new_table_iterator_nanos; uint64_t new_table_iterator_nanos{};
// Time spent on seeking a key in data/index blocks // Time spent on seeking a key in data/index blocks
uint64_t block_seek_nanos; uint64_t block_seek_nanos{};
// Time spent on finding or creating a table reader // Time spent on finding or creating a table reader
uint64_t find_table_nanos; uint64_t find_table_nanos{};
// total number of mem table bloom hits // total number of mem table bloom hits
uint64_t bloom_memtable_hit_count; uint64_t bloom_memtable_hit_count{};
// total number of mem table bloom misses // total number of mem table bloom misses
uint64_t bloom_memtable_miss_count; uint64_t bloom_memtable_miss_count{};
// total number of SST table bloom hits // total number of SST table bloom hits
uint64_t bloom_sst_hit_count; uint64_t bloom_sst_hit_count{};
// total number of SST table bloom misses // total number of SST table bloom misses
uint64_t bloom_sst_miss_count; uint64_t bloom_sst_miss_count{};
// Time spent waiting on key locks in transaction lock manager. // Time spent waiting on key locks in transaction lock manager.
uint64_t key_lock_wait_time; uint64_t key_lock_wait_time{};
// number of times acquiring a lock was blocked by another transaction. // number of times acquiring a lock was blocked by another transaction.
uint64_t key_lock_wait_count; uint64_t key_lock_wait_count{};
// Total time spent in Env filesystem operations. These are only populated // Total time spent in Env filesystem operations. These are only populated
// when TimedEnv is used. // when TimedEnv is used.
uint64_t env_new_sequential_file_nanos; uint64_t env_new_sequential_file_nanos{};
uint64_t env_new_random_access_file_nanos; uint64_t env_new_random_access_file_nanos{};
uint64_t env_new_writable_file_nanos; uint64_t env_new_writable_file_nanos{};
uint64_t env_reuse_writable_file_nanos; uint64_t env_reuse_writable_file_nanos{};
uint64_t env_new_random_rw_file_nanos; uint64_t env_new_random_rw_file_nanos{};
uint64_t env_new_directory_nanos; uint64_t env_new_directory_nanos{};
uint64_t env_file_exists_nanos; uint64_t env_file_exists_nanos{};
uint64_t env_get_children_nanos; uint64_t env_get_children_nanos{};
uint64_t env_get_children_file_attributes_nanos; uint64_t env_get_children_file_attributes_nanos{};
uint64_t env_delete_file_nanos; uint64_t env_delete_file_nanos{};
uint64_t env_create_dir_nanos; uint64_t env_create_dir_nanos{};
uint64_t env_create_dir_if_missing_nanos; uint64_t env_create_dir_if_missing_nanos{};
uint64_t env_delete_dir_nanos; uint64_t env_delete_dir_nanos{};
uint64_t env_get_file_size_nanos; uint64_t env_get_file_size_nanos{};
uint64_t env_get_file_modification_time_nanos; uint64_t env_get_file_modification_time_nanos{};
uint64_t env_rename_file_nanos; uint64_t env_rename_file_nanos{};
uint64_t env_link_file_nanos; uint64_t env_link_file_nanos{};
uint64_t env_lock_file_nanos; uint64_t env_lock_file_nanos{};
uint64_t env_unlock_file_nanos; uint64_t env_unlock_file_nanos{};
uint64_t env_new_logger_nanos; uint64_t env_new_logger_nanos{};
uint64_t get_cpu_nanos; uint64_t get_cpu_nanos{};
uint64_t iter_next_cpu_nanos; uint64_t iter_next_cpu_nanos{};
uint64_t iter_prev_cpu_nanos; uint64_t iter_prev_cpu_nanos{};
uint64_t iter_seek_cpu_nanos; uint64_t iter_seek_cpu_nanos{};
// Time spent in encrypting data. Populated when EncryptedEnv is used. // Time spent in encrypting data. Populated when EncryptedEnv is used.
uint64_t encrypt_data_nanos; uint64_t encrypt_data_nanos{};
// Time spent in decrypting data. Populated when EncryptedEnv is used. // Time spent in decrypting data. Populated when EncryptedEnv is used.
uint64_t decrypt_data_nanos; uint64_t decrypt_data_nanos{};
std::map<uint32_t, PerfContextByLevel>* level_to_perf_context = nullptr; std::map<uint32_t, PerfContextByLevel>* level_to_perf_context = nullptr;
bool per_level_perf_context_enabled = false; bool per_level_perf_context_enabled = false;
......
...@@ -15,7 +15,7 @@ PerfContext perf_context; ...@@ -15,7 +15,7 @@ PerfContext perf_context;
#if defined(OS_SOLARIS) #if defined(OS_SOLARIS)
__thread PerfContext perf_context_; __thread PerfContext perf_context_;
#else #else
thread_local PerfContext perf_context; __thread PerfContext perf_context;
#endif #endif
#endif #endif
...@@ -31,306 +31,6 @@ PerfContext* get_perf_context() { ...@@ -31,306 +31,6 @@ PerfContext* get_perf_context() {
#endif #endif
} }
PerfContext::~PerfContext() {
#if !defined(NPERF_CONTEXT) && defined(ROCKSDB_SUPPORT_THREAD_LOCAL) && !defined(OS_SOLARIS)
ClearPerLevelPerfContext();
#endif
}
PerfContext::PerfContext(const PerfContext& other) {
#ifdef NPERF_CONTEXT
(void)other;
#else
user_key_comparison_count = other.user_key_comparison_count;
block_cache_hit_count = other.block_cache_hit_count;
block_read_count = other.block_read_count;
block_read_byte = other.block_read_byte;
block_read_time = other.block_read_time;
block_cache_index_hit_count = other.block_cache_index_hit_count;
index_block_read_count = other.index_block_read_count;
block_cache_filter_hit_count = other.block_cache_filter_hit_count;
filter_block_read_count = other.filter_block_read_count;
compression_dict_block_read_count = other.compression_dict_block_read_count;
block_checksum_time = other.block_checksum_time;
block_decompress_time = other.block_decompress_time;
get_read_bytes = other.get_read_bytes;
multiget_read_bytes = other.multiget_read_bytes;
iter_read_bytes = other.iter_read_bytes;
internal_key_skipped_count = other.internal_key_skipped_count;
internal_delete_skipped_count = other.internal_delete_skipped_count;
internal_recent_skipped_count = other.internal_recent_skipped_count;
internal_merge_count = other.internal_merge_count;
write_wal_time = other.write_wal_time;
get_snapshot_time = other.get_snapshot_time;
get_from_memtable_time = other.get_from_memtable_time;
get_from_memtable_count = other.get_from_memtable_count;
get_post_process_time = other.get_post_process_time;
get_from_output_files_time = other.get_from_output_files_time;
seek_on_memtable_time = other.seek_on_memtable_time;
seek_on_memtable_count = other.seek_on_memtable_count;
next_on_memtable_count = other.next_on_memtable_count;
prev_on_memtable_count = other.prev_on_memtable_count;
seek_child_seek_time = other.seek_child_seek_time;
seek_child_seek_count = other.seek_child_seek_count;
seek_min_heap_time = other.seek_min_heap_time;
seek_internal_seek_time = other.seek_internal_seek_time;
find_next_user_entry_time = other.find_next_user_entry_time;
write_pre_and_post_process_time = other.write_pre_and_post_process_time;
write_memtable_time = other.write_memtable_time;
write_delay_time = other.write_delay_time;
write_thread_wait_nanos = other.write_thread_wait_nanos;
write_scheduling_flushes_compactions_time =
other.write_scheduling_flushes_compactions_time;
db_mutex_lock_nanos = other.db_mutex_lock_nanos;
db_condition_wait_nanos = other.db_condition_wait_nanos;
merge_operator_time_nanos = other.merge_operator_time_nanos;
read_index_block_nanos = other.read_index_block_nanos;
read_filter_block_nanos = other.read_filter_block_nanos;
new_table_block_iter_nanos = other.new_table_block_iter_nanos;
new_table_iterator_nanos = other.new_table_iterator_nanos;
block_seek_nanos = other.block_seek_nanos;
find_table_nanos = other.find_table_nanos;
bloom_memtable_hit_count = other.bloom_memtable_hit_count;
bloom_memtable_miss_count = other.bloom_memtable_miss_count;
bloom_sst_hit_count = other.bloom_sst_hit_count;
bloom_sst_miss_count = other.bloom_sst_miss_count;
key_lock_wait_time = other.key_lock_wait_time;
key_lock_wait_count = other.key_lock_wait_count;
env_new_sequential_file_nanos = other.env_new_sequential_file_nanos;
env_new_random_access_file_nanos = other.env_new_random_access_file_nanos;
env_new_writable_file_nanos = other.env_new_writable_file_nanos;
env_reuse_writable_file_nanos = other.env_reuse_writable_file_nanos;
env_new_random_rw_file_nanos = other.env_new_random_rw_file_nanos;
env_new_directory_nanos = other.env_new_directory_nanos;
env_file_exists_nanos = other.env_file_exists_nanos;
env_get_children_nanos = other.env_get_children_nanos;
env_get_children_file_attributes_nanos =
other.env_get_children_file_attributes_nanos;
env_delete_file_nanos = other.env_delete_file_nanos;
env_create_dir_nanos = other.env_create_dir_nanos;
env_create_dir_if_missing_nanos = other.env_create_dir_if_missing_nanos;
env_delete_dir_nanos = other.env_delete_dir_nanos;
env_get_file_size_nanos = other.env_get_file_size_nanos;
env_get_file_modification_time_nanos =
other.env_get_file_modification_time_nanos;
env_rename_file_nanos = other.env_rename_file_nanos;
env_link_file_nanos = other.env_link_file_nanos;
env_lock_file_nanos = other.env_lock_file_nanos;
env_unlock_file_nanos = other.env_unlock_file_nanos;
env_new_logger_nanos = other.env_new_logger_nanos;
get_cpu_nanos = other.get_cpu_nanos;
iter_next_cpu_nanos = other.iter_next_cpu_nanos;
iter_prev_cpu_nanos = other.iter_prev_cpu_nanos;
iter_seek_cpu_nanos = other.iter_seek_cpu_nanos;
if (per_level_perf_context_enabled && level_to_perf_context != nullptr) {
ClearPerLevelPerfContext();
}
if (other.level_to_perf_context != nullptr) {
level_to_perf_context = new std::map<uint32_t, PerfContextByLevel>();
*level_to_perf_context = *other.level_to_perf_context;
}
per_level_perf_context_enabled = other.per_level_perf_context_enabled;
#endif
}
PerfContext::PerfContext(PerfContext&& other) noexcept {
#ifdef NPERF_CONTEXT
(void)other;
#else
user_key_comparison_count = other.user_key_comparison_count;
block_cache_hit_count = other.block_cache_hit_count;
block_read_count = other.block_read_count;
block_read_byte = other.block_read_byte;
block_read_time = other.block_read_time;
block_cache_index_hit_count = other.block_cache_index_hit_count;
index_block_read_count = other.index_block_read_count;
block_cache_filter_hit_count = other.block_cache_filter_hit_count;
filter_block_read_count = other.filter_block_read_count;
compression_dict_block_read_count = other.compression_dict_block_read_count;
block_checksum_time = other.block_checksum_time;
block_decompress_time = other.block_decompress_time;
get_read_bytes = other.get_read_bytes;
multiget_read_bytes = other.multiget_read_bytes;
iter_read_bytes = other.iter_read_bytes;
internal_key_skipped_count = other.internal_key_skipped_count;
internal_delete_skipped_count = other.internal_delete_skipped_count;
internal_recent_skipped_count = other.internal_recent_skipped_count;
internal_merge_count = other.internal_merge_count;
write_wal_time = other.write_wal_time;
get_snapshot_time = other.get_snapshot_time;
get_from_memtable_time = other.get_from_memtable_time;
get_from_memtable_count = other.get_from_memtable_count;
get_post_process_time = other.get_post_process_time;
get_from_output_files_time = other.get_from_output_files_time;
seek_on_memtable_time = other.seek_on_memtable_time;
seek_on_memtable_count = other.seek_on_memtable_count;
next_on_memtable_count = other.next_on_memtable_count;
prev_on_memtable_count = other.prev_on_memtable_count;
seek_child_seek_time = other.seek_child_seek_time;
seek_child_seek_count = other.seek_child_seek_count;
seek_min_heap_time = other.seek_min_heap_time;
seek_internal_seek_time = other.seek_internal_seek_time;
find_next_user_entry_time = other.find_next_user_entry_time;
write_pre_and_post_process_time = other.write_pre_and_post_process_time;
write_memtable_time = other.write_memtable_time;
write_delay_time = other.write_delay_time;
write_thread_wait_nanos = other.write_thread_wait_nanos;
write_scheduling_flushes_compactions_time =
other.write_scheduling_flushes_compactions_time;
db_mutex_lock_nanos = other.db_mutex_lock_nanos;
db_condition_wait_nanos = other.db_condition_wait_nanos;
merge_operator_time_nanos = other.merge_operator_time_nanos;
read_index_block_nanos = other.read_index_block_nanos;
read_filter_block_nanos = other.read_filter_block_nanos;
new_table_block_iter_nanos = other.new_table_block_iter_nanos;
new_table_iterator_nanos = other.new_table_iterator_nanos;
block_seek_nanos = other.block_seek_nanos;
find_table_nanos = other.find_table_nanos;
bloom_memtable_hit_count = other.bloom_memtable_hit_count;
bloom_memtable_miss_count = other.bloom_memtable_miss_count;
bloom_sst_hit_count = other.bloom_sst_hit_count;
bloom_sst_miss_count = other.bloom_sst_miss_count;
key_lock_wait_time = other.key_lock_wait_time;
key_lock_wait_count = other.key_lock_wait_count;
env_new_sequential_file_nanos = other.env_new_sequential_file_nanos;
env_new_random_access_file_nanos = other.env_new_random_access_file_nanos;
env_new_writable_file_nanos = other.env_new_writable_file_nanos;
env_reuse_writable_file_nanos = other.env_reuse_writable_file_nanos;
env_new_random_rw_file_nanos = other.env_new_random_rw_file_nanos;
env_new_directory_nanos = other.env_new_directory_nanos;
env_file_exists_nanos = other.env_file_exists_nanos;
env_get_children_nanos = other.env_get_children_nanos;
env_get_children_file_attributes_nanos =
other.env_get_children_file_attributes_nanos;
env_delete_file_nanos = other.env_delete_file_nanos;
env_create_dir_nanos = other.env_create_dir_nanos;
env_create_dir_if_missing_nanos = other.env_create_dir_if_missing_nanos;
env_delete_dir_nanos = other.env_delete_dir_nanos;
env_get_file_size_nanos = other.env_get_file_size_nanos;
env_get_file_modification_time_nanos =
other.env_get_file_modification_time_nanos;
env_rename_file_nanos = other.env_rename_file_nanos;
env_link_file_nanos = other.env_link_file_nanos;
env_lock_file_nanos = other.env_lock_file_nanos;
env_unlock_file_nanos = other.env_unlock_file_nanos;
env_new_logger_nanos = other.env_new_logger_nanos;
get_cpu_nanos = other.get_cpu_nanos;
iter_next_cpu_nanos = other.iter_next_cpu_nanos;
iter_prev_cpu_nanos = other.iter_prev_cpu_nanos;
iter_seek_cpu_nanos = other.iter_seek_cpu_nanos;
if (per_level_perf_context_enabled && level_to_perf_context != nullptr) {