1 /*
2 Portions Copyright (c) 2015-Present, Facebook, Inc.
3 Portions Copyright (c) 2012, Monty Program Ab
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; version 2 of the License.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17
18 /* This C++ file's header file */
19 #include "./rdb_perf_context.h"
20
21 /* C++ system header files */
22 #include <string>
23
24 /* RocksDB header files */
25 #include "rocksdb/iostats_context.h"
26 #include "rocksdb/perf_context.h"
27
28 /* MyRocks header files */
29 #include "./ha_rocksdb_proto.h"
30
31 namespace myrocks {
32
33 // To add a new metric:
34 // 1. Update the PC enum in rdb_perf_context.h
35 // 2. Update sections (A), (B), and (C) below
36 // 3. Update perf_context.test and show_engine.test
37
38 std::string rdb_pc_stat_types[] = {
39 // (A) These should be in the same order as the PC enum
40 "USER_KEY_COMPARISON_COUNT",
41 "BLOCK_CACHE_HIT_COUNT",
42 "BLOCK_READ_COUNT",
43 "BLOCK_READ_BYTE",
44 "BLOCK_READ_TIME",
45 "BLOCK_CHECKSUM_TIME",
46 "BLOCK_DECOMPRESS_TIME",
47 "INTERNAL_KEY_SKIPPED_COUNT",
48 "INTERNAL_DELETE_SKIPPED_COUNT",
49 "GET_SNAPSHOT_TIME",
50 "GET_FROM_MEMTABLE_TIME",
51 "GET_FROM_MEMTABLE_COUNT",
52 "GET_POST_PROCESS_TIME",
53 "GET_FROM_OUTPUT_FILES_TIME",
54 "SEEK_ON_MEMTABLE_TIME",
55 "SEEK_ON_MEMTABLE_COUNT",
56 "SEEK_CHILD_SEEK_TIME",
57 "SEEK_CHILD_SEEK_COUNT",
58 "SEEK_IN_HEAP_TIME",
59 "SEEK_INTERNAL_SEEK_TIME",
60 "FIND_NEXT_USER_ENTRY_TIME",
61 "WRITE_WAL_TIME",
62 "WRITE_MEMTABLE_TIME",
63 "WRITE_DELAY_TIME",
64 "WRITE_PRE_AND_POST_PROCESS_TIME",
65 "DB_MUTEX_LOCK_NANOS",
66 "DB_CONDITION_WAIT_NANOS",
67 "MERGE_OPERATOR_TIME_NANOS",
68 "READ_INDEX_BLOCK_NANOS",
69 "READ_FILTER_BLOCK_NANOS",
70 "NEW_TABLE_BLOCK_ITER_NANOS",
71 "NEW_TABLE_ITERATOR_NANOS",
72 "BLOCK_SEEK_NANOS",
73 "FIND_TABLE_NANOS",
74 "IO_THREAD_POOL_ID",
75 "IO_BYTES_WRITTEN",
76 "IO_BYTES_READ",
77 "IO_OPEN_NANOS",
78 "IO_ALLOCATE_NANOS",
79 "IO_WRITE_NANOS",
80 "IO_READ_NANOS",
81 "IO_RANGE_SYNC_NANOS",
82 "IO_LOGGER_NANOS"};
83
84 #define IO_PERF_RECORD(_field_) \
85 do { \
86 if (rocksdb::perf_context._field_ > 0) \
87 counters->m_value[idx] += rocksdb::perf_context._field_; \
88 idx++; \
89 } while (0)
90 #define IO_STAT_RECORD(_field_) \
91 do { \
92 if (rocksdb::iostats_context._field_ > 0) \
93 counters->m_value[idx] += rocksdb::iostats_context._field_; \
94 idx++; \
95 } while (0)
96
harvest_diffs(Rdb_atomic_perf_counters * const counters)97 static void harvest_diffs(Rdb_atomic_perf_counters *const counters) {
98 // (C) These should be in the same order as the PC enum
99 size_t idx = 0;
100 IO_PERF_RECORD(user_key_comparison_count);
101 IO_PERF_RECORD(block_cache_hit_count);
102 IO_PERF_RECORD(block_read_count);
103 IO_PERF_RECORD(block_read_byte);
104 IO_PERF_RECORD(block_read_time);
105 IO_PERF_RECORD(block_checksum_time);
106 IO_PERF_RECORD(block_decompress_time);
107 IO_PERF_RECORD(internal_key_skipped_count);
108 IO_PERF_RECORD(internal_delete_skipped_count);
109 IO_PERF_RECORD(get_snapshot_time);
110 IO_PERF_RECORD(get_from_memtable_time);
111 IO_PERF_RECORD(get_from_memtable_count);
112 IO_PERF_RECORD(get_post_process_time);
113 IO_PERF_RECORD(get_from_output_files_time);
114 IO_PERF_RECORD(seek_on_memtable_time);
115 IO_PERF_RECORD(seek_on_memtable_count);
116 IO_PERF_RECORD(seek_child_seek_time);
117 IO_PERF_RECORD(seek_child_seek_count);
118 IO_PERF_RECORD(seek_min_heap_time);
119 IO_PERF_RECORD(seek_internal_seek_time);
120 IO_PERF_RECORD(find_next_user_entry_time);
121 IO_PERF_RECORD(write_wal_time);
122 IO_PERF_RECORD(write_memtable_time);
123 IO_PERF_RECORD(write_delay_time);
124 IO_PERF_RECORD(write_pre_and_post_process_time);
125 IO_PERF_RECORD(db_mutex_lock_nanos);
126 IO_PERF_RECORD(db_condition_wait_nanos);
127 IO_PERF_RECORD(merge_operator_time_nanos);
128 IO_PERF_RECORD(read_index_block_nanos);
129 IO_PERF_RECORD(read_filter_block_nanos);
130 IO_PERF_RECORD(new_table_block_iter_nanos);
131 IO_PERF_RECORD(new_table_iterator_nanos);
132 IO_PERF_RECORD(block_seek_nanos);
133 IO_PERF_RECORD(find_table_nanos);
134 IO_STAT_RECORD(thread_pool_id);
135 IO_STAT_RECORD(bytes_written);
136 IO_STAT_RECORD(bytes_read);
137 IO_STAT_RECORD(open_nanos);
138 IO_STAT_RECORD(allocate_nanos);
139 IO_STAT_RECORD(write_nanos);
140 IO_STAT_RECORD(read_nanos);
141 IO_STAT_RECORD(range_sync_nanos);
142 IO_STAT_RECORD(logger_nanos);
143 }
144
145 #undef IO_PERF_DIFF
146 #undef IO_STAT_DIFF
147
148 static Rdb_atomic_perf_counters rdb_global_perf_counters;
149
rdb_get_global_perf_counters(Rdb_perf_counters * const counters)150 void rdb_get_global_perf_counters(Rdb_perf_counters *const counters) {
151 DBUG_ASSERT(counters != nullptr);
152
153 counters->load(rdb_global_perf_counters);
154 }
155
load(const Rdb_atomic_perf_counters & atomic_counters)156 void Rdb_perf_counters::load(const Rdb_atomic_perf_counters &atomic_counters) {
157 for (int i = 0; i < PC_MAX_IDX; i++) {
158 m_value[i] = atomic_counters.m_value[i].load(std::memory_order_relaxed);
159 }
160 }
161
start(const uint32_t perf_context_level)162 bool Rdb_io_perf::start(const uint32_t perf_context_level) {
163 const rocksdb::PerfLevel perf_level =
164 static_cast<rocksdb::PerfLevel>(perf_context_level);
165
166 if (rocksdb::GetPerfLevel() != perf_level) {
167 rocksdb::SetPerfLevel(perf_level);
168 }
169
170 if (perf_level == rocksdb::kDisable) {
171 return false;
172 }
173
174 rocksdb::perf_context.Reset();
175 rocksdb::iostats_context.Reset();
176 return true;
177 }
178
end_and_record(const uint32_t perf_context_level)179 void Rdb_io_perf::end_and_record(const uint32_t perf_context_level) {
180 const rocksdb::PerfLevel perf_level =
181 static_cast<rocksdb::PerfLevel>(perf_context_level);
182
183 if (perf_level == rocksdb::kDisable) {
184 return;
185 }
186
187 if (m_atomic_counters) {
188 harvest_diffs(m_atomic_counters);
189 }
190 harvest_diffs(&rdb_global_perf_counters);
191
192 if (m_shared_io_perf_read && (rocksdb::perf_context.block_read_byte != 0 ||
193 rocksdb::perf_context.block_read_count != 0 ||
194 rocksdb::perf_context.block_read_time != 0)) {
195 my_io_perf_t io_perf_read;
196
197 io_perf_read.init();
198 io_perf_read.bytes = rocksdb::perf_context.block_read_byte;
199 io_perf_read.requests = rocksdb::perf_context.block_read_count;
200
201 /*
202 Rocksdb does not distinguish between I/O service and wait time, so just
203 use svc time.
204 */
205 io_perf_read.svc_time_max = io_perf_read.svc_time =
206 rocksdb::perf_context.block_read_time;
207
208 m_shared_io_perf_read->sum(io_perf_read);
209 }
210 }
211
212 } // namespace myrocks
213