be/src/cloud/cloud_tablet_hotspot.cpp
Line | Count | Source |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | |
18 | | #include "cloud/cloud_tablet_hotspot.h" |
19 | | |
20 | | #include <algorithm> |
21 | | #include <chrono> |
22 | | #include <cmath> |
23 | | #include <cstdint> |
24 | | #include <mutex> |
25 | | #include <vector> |
26 | | |
27 | | #include "runtime/memory/global_memory_arbitrator.h" |
28 | | #include "storage/tablet/base_tablet.h" |
29 | | |
30 | | namespace doris { |
31 | | |
32 | | namespace { |
33 | | |
34 | | using HotPartitionSnapshot = |
35 | | std::unordered_map<TabletHotspotMapKey, std::unordered_map<int64_t, TabletHotspotMapValue>, |
36 | | MapKeyHash>; |
37 | | |
38 | | constexpr uint64_t kCountHeartbeatInterval = 500000; |
39 | | constexpr uint64_t kNewCounterLogInterval = 4096; |
40 | | constexpr size_t kCompactBucketMultiplier = 4; |
41 | | constexpr size_t kCompactEraseRatioDivisor = 4; |
42 | | |
43 | | using SystemTimePoint = std::chrono::system_clock::time_point; |
44 | | using SteadyClock = std::chrono::steady_clock; |
45 | | |
46 | 8 | double bytes_to_mb(int64_t bytes) { |
47 | 8 | return static_cast<double>(bytes) / (1024.0 * 1024.0); |
48 | 8 | } |
49 | | |
50 | 2 | double ratio_or_zero(uint64_t numerator, uint64_t denominator) { |
51 | 2 | if (denominator == 0) { |
52 | 0 | return 0.0; |
53 | 0 | } |
54 | 2 | return static_cast<double>(numerator) / static_cast<double>(denominator); |
55 | 2 | } |
56 | | |
57 | 8 | int64_t process_memory_usage_for_diag() { |
58 | | #ifdef BE_TEST |
59 | | return 0; |
60 | | #else |
61 | 8 | return GlobalMemoryArbitrator::process_memory_usage(); |
62 | 8 | #endif |
63 | 8 | } |
64 | | |
65 | 18 | uint64_t count_hot_partition_entries(const HotPartitionSnapshot& snapshot) { |
66 | 18 | uint64_t entries = 0; |
67 | 17.4k | for (const auto& [_, partition_to_value] : snapshot) { |
68 | 17.4k | entries += partition_to_value.size(); |
69 | 17.4k | } |
70 | 18 | return entries; |
71 | 18 | } |
72 | | |
73 | | bool should_compact_slot(size_t slot_size_before, size_t slot_size_after, size_t bucket_count_after, |
74 | 6.14k | size_t erased_count) { |
75 | 6.14k | if (erased_count == 0) { |
76 | 6.14k | return false; |
77 | 6.14k | } |
78 | 4 | if (slot_size_after == 0) { |
79 | 4 | return true; |
80 | 4 | } |
81 | 0 | return bucket_count_after > (kCompactBucketMultiplier * slot_size_after) || |
82 | 0 | (slot_size_before > 0 && erased_count * kCompactEraseRatioDivisor >= slot_size_before); |
83 | 4 | } |
84 | | |
85 | | } // namespace |
86 | | |
87 | 1.47M | void TabletHotspot::count(const BaseTablet& tablet) { |
88 | 1.47M | count(tablet.tablet_id(), tablet.table_id(), tablet.index_id(), tablet.partition_id()); |
89 | 1.47M | } |
90 | | |
91 | | void TabletHotspot::count(int64_t tablet_id, int64_t table_id, int64_t index_id, |
92 | 1.47M | int64_t partition_id) { |
93 | 1.47M | const uint64_t count_calls_total = |
94 | 1.47M | _count_calls_total.fetch_add(1, std::memory_order_relaxed) + 1; |
95 | | |
96 | 1.47M | size_t slot_idx = tablet_id % s_slot_size; |
97 | 1.47M | auto& slot = _tablets_hotspot[slot_idx]; |
98 | 1.47M | bool should_log_new_counter = false; |
99 | 1.47M | uint64_t new_counter_total = 0; |
100 | 1.47M | { |
101 | 1.47M | std::lock_guard lock(slot.mtx); |
102 | 1.47M | HotspotCounterPtr counter; |
103 | 1.47M | if (auto iter = slot.map.find(tablet_id); iter == slot.map.end()) { |
104 | 90.8k | counter = std::make_shared<HotspotCounter>(table_id, index_id, partition_id); |
105 | 90.8k | slot.map.insert(std::make_pair(tablet_id, counter)); |
106 | 90.8k | new_counter_total = _new_counter_total.fetch_add(1, std::memory_order_relaxed) + 1; |
107 | 90.8k | should_log_new_counter = (new_counter_total % kNewCounterLogInterval == 0); |
108 | 1.38M | } else { |
109 | 1.38M | counter = iter->second; |
110 | 1.38M | _existing_hit_total.fetch_add(1, std::memory_order_relaxed); |
111 | 1.38M | } |
112 | 1.47M | counter->last_access_time = std::chrono::system_clock::now(); |
113 | 1.47M | counter->cur_counter.fetch_add(1, std::memory_order_relaxed); |
114 | 1.47M | } |
115 | | |
116 | 1.47M | if (should_log_new_counter) { |
117 | 22 | LOG(INFO) << "tablet_hotspot_diag new_counter_total=" << new_counter_total |
118 | 22 | << " count_calls_total=" << count_calls_total |
119 | 22 | << " existing_hit_total=" << _existing_hit_total.load(std::memory_order_relaxed); |
120 | 22 | } |
121 | 1.47M | if (count_calls_total % kCountHeartbeatInterval == 0) { |
122 | 2 | LOG(INFO) << "tablet_hotspot_diag count_heartbeat count_calls_total=" << count_calls_total |
123 | 2 | << " existing_hit_total=" << _existing_hit_total.load(std::memory_order_relaxed) |
124 | 2 | << " new_counter_total=" << _new_counter_total.load(std::memory_order_relaxed); |
125 | 2 | } |
126 | 1.47M | } |
127 | | |
128 | 7 | TabletHotspot::TabletHotspot(bool start_counter_thread) { |
129 | 7 | if (start_counter_thread) { |
130 | 1 | _counter_thread = std::thread(&TabletHotspot::make_dot_point, this); |
131 | 1 | } |
132 | 7 | } |
133 | | |
134 | 6 | TabletHotspot::~TabletHotspot() { |
135 | 6 | { |
136 | 6 | std::lock_guard lock(_mtx); |
137 | 6 | _closed = true; |
138 | 6 | } |
139 | 6 | _cond.notify_all(); |
140 | 6 | if (_counter_thread.joinable()) { |
141 | 0 | _counter_thread.join(); |
142 | 0 | } |
143 | 6 | } |
144 | | |
145 | | void get_return_partitions( |
146 | | const std::unordered_map<TabletHotspotMapKey, |
147 | | std::unordered_map<int64_t, TabletHotspotMapValue>, MapKeyHash>& |
148 | | hot_partition, |
149 | | const std::unordered_map<TabletHotspotMapKey, |
150 | | std::unordered_map<int64_t, TabletHotspotMapValue>, MapKeyHash>& |
151 | | last_hot_partition, |
152 | 6 | std::vector<THotTableMessage>* hot_tables, int& return_partitions, int N) { |
153 | 53 | for (const auto& [key, partition_to_value] : hot_partition) { |
154 | 53 | THotTableMessage msg; |
155 | 53 | msg.table_id = key.first; |
156 | 53 | msg.index_id = key.second; |
157 | 54 | for (const auto& [partition_id, value] : partition_to_value) { |
158 | 54 | if (return_partitions > N) { |
159 | 1 | return; |
160 | 1 | } |
161 | 53 | auto last_value_iter = last_hot_partition.find(key); |
162 | 53 | if (last_value_iter != last_hot_partition.end()) { |
163 | 0 | auto last_partition_iter = last_value_iter->second.find(partition_id); |
164 | 0 | if (last_partition_iter != last_value_iter->second.end()) { |
165 | 0 | const auto& last_value = last_partition_iter->second; |
166 | 0 | if (std::abs(static_cast<int64_t>(value.qpd) - |
167 | 0 | static_cast<int64_t>(last_value.qpd)) < 5 && |
168 | 0 | std::abs(static_cast<int64_t>(value.qpw) - |
169 | 0 | static_cast<int64_t>(last_value.qpw)) < 10 && |
170 | 0 | std::abs(static_cast<int64_t>(value.last_access_time) - |
171 | 0 | static_cast<int64_t>(last_value.last_access_time)) < 60) { |
172 | 0 | LOG(INFO) << "skip partition_id=" << partition_id << " qpd=" << value.qpd |
173 | 0 | << " qpw=" << value.qpw |
174 | 0 | << " last_access_time=" << value.last_access_time |
175 | 0 | << " last_qpd=" << last_value.qpd |
176 | 0 | << " last_qpw=" << last_value.qpw |
177 | 0 | << " last_access_time=" << last_value.last_access_time; |
178 | 0 | continue; |
179 | 0 | } |
180 | 0 | } |
181 | 0 | } |
182 | 53 | THotPartition new_hot_partition; |
183 | 53 | new_hot_partition.__set_partition_id(partition_id); |
184 | 53 | new_hot_partition.__set_query_per_day(value.qpd); |
185 | 53 | new_hot_partition.__set_query_per_week(value.qpw); |
186 | 53 | new_hot_partition.__set_last_access_time(value.last_access_time); |
187 | 53 | msg.hot_partitions.push_back(new_hot_partition); |
188 | 53 | return_partitions++; |
189 | 53 | } |
190 | 52 | msg.__isset.hot_partitions = !msg.hot_partitions.empty(); |
191 | 52 | hot_tables->push_back(std::move(msg)); |
192 | 52 | } |
193 | 6 | } |
194 | | |
195 | 3 | void TabletHotspot::get_top_n_hot_partition(std::vector<THotTableMessage>* hot_tables) { |
196 | 3 | const uint64_t call_id = |
197 | 3 | _get_top_n_hot_partition_call_total.fetch_add(1, std::memory_order_relaxed) + 1; |
198 | 3 | uint64_t last_day_tables_before = 0; |
199 | 3 | uint64_t last_day_entries_before = 0; |
200 | 3 | uint64_t last_week_tables_before = 0; |
201 | 3 | uint64_t last_week_entries_before = 0; |
202 | 3 | { |
203 | 3 | std::lock_guard lock(_last_partitions_mtx); |
204 | 3 | last_day_tables_before = _last_day_hot_partitions.size(); |
205 | 3 | last_day_entries_before = count_hot_partition_entries(_last_day_hot_partitions); |
206 | 3 | last_week_tables_before = _last_week_hot_partitions.size(); |
207 | 3 | last_week_entries_before = count_hot_partition_entries(_last_week_hot_partitions); |
208 | 3 | } |
209 | 3 | const int64_t process_mem_before = process_memory_usage_for_diag(); |
210 | | |
211 | | // map<pair<table_id, index_id>, map<partition_id, value>> for day |
212 | 3 | std::unordered_map<TabletHotspotMapKey, std::unordered_map<int64_t, TabletHotspotMapValue>, |
213 | 3 | MapKeyHash> |
214 | 3 | day_hot_partitions; |
215 | | // map<pair<table_id, index_id>, map<partition_id, value>> for week |
216 | 3 | std::unordered_map<TabletHotspotMapKey, std::unordered_map<int64_t, TabletHotspotMapValue>, |
217 | 3 | MapKeyHash> |
218 | 3 | week_hot_partitions; |
219 | | |
220 | 3.07k | std::for_each(_tablets_hotspot.begin(), _tablets_hotspot.end(), [&](HotspotMap& map) { |
221 | 3.07k | std::lock_guard lock(map.mtx); |
222 | 85.4k | for (auto& [_, counter] : map.map) { |
223 | 85.4k | if (counter->qpd() != 0) { |
224 | 85.4k | auto& hot_partition = day_hot_partitions[std::make_pair( |
225 | 85.4k | counter->table_id, counter->index_id)][counter->partition_id]; |
226 | 85.4k | hot_partition.qpd = std::max(hot_partition.qpd, counter->qpd()); |
227 | 85.4k | hot_partition.qpw = std::max(hot_partition.qpw, counter->qpw()); |
228 | 85.4k | hot_partition.last_access_time = |
229 | 85.4k | std::max<int64_t>(hot_partition.last_access_time, |
230 | 85.4k | std::chrono::duration_cast<std::chrono::seconds>( |
231 | 85.4k | counter->last_access_time.time_since_epoch()) |
232 | 85.4k | .count()); |
233 | 85.4k | } else if (counter->qpw() != 0) { |
234 | 0 | auto& hot_partition = week_hot_partitions[std::make_pair( |
235 | 0 | counter->table_id, counter->index_id)][counter->partition_id]; |
236 | 0 | hot_partition.qpd = 0; |
237 | 0 | hot_partition.qpw = std::max(hot_partition.qpw, counter->qpw()); |
238 | 0 | hot_partition.last_access_time = |
239 | 0 | std::max<int64_t>(hot_partition.last_access_time, |
240 | 0 | std::chrono::duration_cast<std::chrono::seconds>( |
241 | 0 | counter->last_access_time.time_since_epoch()) |
242 | 0 | .count()); |
243 | 0 | } |
244 | 85.4k | } |
245 | 3.07k | }); |
246 | 3 | constexpr int N = 50; |
247 | 3 | int return_partitions = 0; |
248 | 3 | const uint64_t day_tables_built = day_hot_partitions.size(); |
249 | 3 | const uint64_t day_entries_built = count_hot_partition_entries(day_hot_partitions); |
250 | 3 | const uint64_t week_tables_built = week_hot_partitions.size(); |
251 | 3 | const uint64_t week_entries_built = count_hot_partition_entries(week_hot_partitions); |
252 | 3 | uint64_t last_day_tables_after = 0; |
253 | 3 | uint64_t last_day_entries_after = 0; |
254 | 3 | uint64_t last_week_tables_after = 0; |
255 | 3 | uint64_t last_week_entries_after = 0; |
256 | | |
257 | 3 | { |
258 | 3 | std::unique_lock lock(_last_partitions_mtx); |
259 | 3 | get_return_partitions(day_hot_partitions, _last_day_hot_partitions, hot_tables, |
260 | 3 | return_partitions, N); |
261 | 3 | get_return_partitions(week_hot_partitions, _last_week_hot_partitions, hot_tables, |
262 | 3 | return_partitions, N); |
263 | | |
264 | 3 | _last_day_hot_partitions = std::move(day_hot_partitions); |
265 | 3 | _last_week_hot_partitions = std::move(week_hot_partitions); |
266 | 3 | last_day_tables_after = _last_day_hot_partitions.size(); |
267 | 3 | last_day_entries_after = count_hot_partition_entries(_last_day_hot_partitions); |
268 | 3 | last_week_tables_after = _last_week_hot_partitions.size(); |
269 | 3 | last_week_entries_after = count_hot_partition_entries(_last_week_hot_partitions); |
270 | 3 | } |
271 | | |
272 | 3 | const int64_t process_mem_after = process_memory_usage_for_diag(); |
273 | | |
274 | 3 | LOG(INFO) << "tablet_hotspot_diag get_top_n_hot_partition call_id=" << call_id |
275 | 3 | << " day_tables_built=" << day_tables_built |
276 | 3 | << " day_entries_built=" << day_entries_built |
277 | 3 | << " week_tables_built=" << week_tables_built |
278 | 3 | << " week_entries_built=" << week_entries_built |
279 | 3 | << " returned_partitions=" << return_partitions |
280 | 3 | << " last_day_tables_before=" << last_day_tables_before |
281 | 3 | << " last_day_entries_before=" << last_day_entries_before |
282 | 3 | << " last_day_tables_after=" << last_day_tables_after |
283 | 3 | << " last_day_entries_after=" << last_day_entries_after |
284 | 3 | << " last_week_tables_before=" << last_week_tables_before |
285 | 3 | << " last_week_entries_before=" << last_week_entries_before |
286 | 3 | << " last_week_tables_after=" << last_week_tables_after |
287 | 3 | << " last_week_entries_after=" << last_week_entries_after |
288 | 3 | << " process_mem_before_mb=" << bytes_to_mb(process_mem_before) |
289 | 3 | << " process_mem_after_mb=" << bytes_to_mb(process_mem_after); |
290 | 3 | } |
291 | | |
292 | 86.1k | void HotspotCounter::make_dot_point() { |
293 | 86.1k | uint64_t value = cur_counter.exchange(0, std::memory_order_acq_rel); |
294 | 86.1k | if (history_counters.size() == week_counters_size) { |
295 | 0 | uint64_t week_counter_remove = history_counters.back(); |
296 | 0 | uint64_t day_counter_remove = history_counters[day_counters_size - 1]; |
297 | 0 | week_history_counter = week_history_counter - week_counter_remove + value; |
298 | 0 | day_history_counter = day_history_counter - day_counter_remove + value; |
299 | 0 | history_counters.pop_back(); |
300 | 86.1k | } else if (history_counters.size() < day_counters_size) { |
301 | 86.1k | week_history_counter += value; |
302 | 86.1k | day_history_counter += value; |
303 | 86.1k | } else { |
304 | 0 | week_history_counter += value; |
305 | 0 | uint64_t day_counter_remove = history_counters[day_counters_size - 1]; |
306 | 0 | day_history_counter = day_history_counter - day_counter_remove + value; |
307 | 0 | } |
308 | 86.1k | history_counters.push_front(value); |
309 | 86.1k | } |
310 | | |
311 | 170k | uint64_t HotspotCounter::qpd() { |
312 | 170k | return day_history_counter + cur_counter.load(); |
313 | 170k | } |
314 | | |
315 | 85.4k | uint64_t HotspotCounter::qpw() { |
316 | 85.4k | return week_history_counter + cur_counter.load(); |
317 | 85.4k | } |
318 | | |
319 | 86.1k | bool TabletHotspot::is_gc_eligible(const HotspotCounter& counter, SystemTimePoint now) { |
320 | 86.1k | const auto week_window = std::chrono::seconds((HotspotCounter::week_counters_size + 1) * |
321 | 86.1k | HotspotCounter::time_interval); |
322 | 86.1k | return counter.last_access_time < now - week_window && |
323 | 86.1k | counter.cur_counter.load(std::memory_order_relaxed) == 0 && |
324 | 86.1k | counter.day_history_counter.load(std::memory_order_relaxed) == 0 && |
325 | 86.1k | counter.week_history_counter.load(std::memory_order_relaxed) == 0; |
326 | 86.1k | } |
327 | | |
328 | 6 | TabletHotspot::MaintenanceStats TabletHotspot::run_maintenance_once(SystemTimePoint now) { |
329 | 6 | MaintenanceStats stats; |
330 | 6 | auto gc_elapsed = SteadyClock::duration::zero(); |
331 | | |
332 | 6.15k | for (size_t slot_idx = 0; slot_idx < s_slot_size; ++slot_idx) { |
333 | 6.14k | auto& slot = _tablets_hotspot[slot_idx]; |
334 | 6.14k | std::vector<HotspotCounterPtr> counters; |
335 | 6.14k | size_t slot_size_before = 0; |
336 | 6.14k | size_t slot_bucket_count_before = 0; |
337 | | |
338 | 6.14k | { |
339 | 6.14k | std::lock_guard lock(slot.mtx); |
340 | 6.14k | slot_size_before = slot.map.size(); |
341 | 6.14k | slot_bucket_count_before = slot.map.bucket_count(); |
342 | 6.14k | stats.total_counters_before_gc += slot_size_before; |
343 | 6.14k | if (slot_size_before > 0) { |
344 | 1.03k | ++stats.non_empty_slots_before_gc; |
345 | 1.03k | } |
346 | 6.14k | stats.max_slot_size_before_gc = |
347 | 6.14k | std::max<uint64_t>(stats.max_slot_size_before_gc, slot_size_before); |
348 | 6.14k | stats.sum_bucket_count_before_gc += slot_bucket_count_before; |
349 | 6.14k | counters.reserve(slot_size_before); |
350 | 86.1k | for (auto& [_, counter] : slot.map) { |
351 | 86.1k | counters.push_back(counter); |
352 | 86.1k | } |
353 | 6.14k | } |
354 | 6.14k | stats.copied_counters += counters.size(); |
355 | 6.14k | std::for_each(counters.begin(), counters.end(), |
356 | 86.1k | [](HotspotCounterPtr& counter) { counter->make_dot_point(); }); |
357 | | |
358 | 6.14k | size_t erased_count = 0; |
359 | 6.14k | bool compacted = false; |
360 | 6.14k | size_t slot_size_after = 0; |
361 | 6.14k | size_t slot_bucket_count_after = 0; |
362 | 6.14k | auto gc_start = SteadyClock::now(); |
363 | 6.14k | { |
364 | 6.14k | std::lock_guard lock(slot.mtx); |
365 | 92.2k | for (auto iter = slot.map.begin(); iter != slot.map.end();) { |
366 | 86.1k | if (is_gc_eligible(*iter->second, now)) { |
367 | 259 | iter = slot.map.erase(iter); |
368 | 259 | ++erased_count; |
369 | 85.8k | } else { |
370 | 85.8k | ++iter; |
371 | 85.8k | } |
372 | 86.1k | } |
373 | | |
374 | 6.14k | if (should_compact_slot(slot_size_before, slot.map.size(), slot.map.bucket_count(), |
375 | 6.14k | erased_count)) { |
376 | 4 | decltype(slot.map) compacted_map; |
377 | 4 | compacted_map.max_load_factor(slot.map.max_load_factor()); |
378 | 4 | compacted_map.reserve(slot.map.size()); |
379 | 4 | for (const auto& [tablet_id, counter] : slot.map) { |
380 | 0 | compacted_map.emplace(tablet_id, counter); |
381 | 0 | } |
382 | 4 | slot.map.swap(compacted_map); |
383 | 4 | compacted = true; |
384 | 4 | } |
385 | | |
386 | 6.14k | slot_size_after = slot.map.size(); |
387 | 6.14k | slot_bucket_count_after = slot.map.bucket_count(); |
388 | 6.14k | stats.total_counters_after_gc += slot_size_after; |
389 | 6.14k | if (slot_size_after > 0) { |
390 | 1.02k | ++stats.non_empty_slots_after_gc; |
391 | 1.02k | } |
392 | 6.14k | stats.max_slot_size_after_gc = |
393 | 6.14k | std::max<uint64_t>(stats.max_slot_size_after_gc, slot_size_after); |
394 | 6.14k | stats.sum_bucket_count_after_gc += slot_bucket_count_after; |
395 | 6.14k | } |
396 | 6.14k | gc_elapsed += SteadyClock::now() - gc_start; |
397 | | |
398 | 6.14k | stats.evicted_counters += erased_count; |
399 | 6.14k | if (compacted) { |
400 | 4 | ++stats.compacted_slots; |
401 | 4 | } |
402 | 6.14k | if (erased_count > 0 || compacted) { |
403 | 4 | LOG(INFO) << "tablet_hotspot_diag gc_slot" |
404 | 4 | << " slot_idx=" << slot_idx << " slot_size_before=" << slot_size_before |
405 | 4 | << " slot_size_after=" << slot_size_after |
406 | 4 | << " bucket_count_before=" << slot_bucket_count_before |
407 | 4 | << " bucket_count_after=" << slot_bucket_count_after |
408 | 4 | << " erased_count=" << erased_count << " compacted=" << compacted; |
409 | 4 | } |
410 | 6.14k | } |
411 | | |
412 | 6 | stats.gc_elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(gc_elapsed).count(); |
413 | 6 | return stats; |
414 | 6 | } |
415 | | |
416 | 1 | void TabletHotspot::make_dot_point() { |
417 | 3 | while (true) { |
418 | 2 | { |
419 | 2 | std::unique_lock lock(_mtx); |
420 | 2 | _cond.wait_for(lock, std::chrono::seconds(HotspotCounter::time_interval), |
421 | 3 | [this]() { return _closed; }); |
422 | 2 | if (_closed) { |
423 | 0 | break; |
424 | 0 | } |
425 | 2 | } |
426 | | |
427 | 2 | const uint64_t round = |
428 | 2 | _make_dot_point_round_total.fetch_add(1, std::memory_order_relaxed) + 1; |
429 | 2 | const uint64_t count_calls_total = _count_calls_total.load(std::memory_order_relaxed); |
430 | 2 | const uint64_t existing_hit_total = _existing_hit_total.load(std::memory_order_relaxed); |
431 | 2 | const uint64_t new_counter_total_before = |
432 | 2 | _new_counter_total.load(std::memory_order_relaxed); |
433 | 2 | const int64_t process_mem_before = process_memory_usage_for_diag(); |
434 | | |
435 | 2 | const auto now = std::chrono::system_clock::now(); |
436 | 2 | const MaintenanceStats stats = run_maintenance_once(now); |
437 | | |
438 | 2 | const int64_t process_mem_after = process_memory_usage_for_diag(); |
439 | 2 | const uint64_t new_counter_total_after = _new_counter_total.load(std::memory_order_relaxed); |
440 | 2 | const uint64_t prev_round_new_counter_total = _last_round_new_counter_total.exchange( |
441 | 2 | new_counter_total_after, std::memory_order_relaxed); |
442 | 2 | const uint64_t new_counter_delta = |
443 | 2 | new_counter_total_after >= prev_round_new_counter_total |
444 | 2 | ? (new_counter_total_after - prev_round_new_counter_total) |
445 | 2 | : 0; |
446 | | |
447 | 2 | LOG(INFO) << "tablet_hotspot_diag make_dot_point round=" << round |
448 | 2 | << " total_counters=" << stats.total_counters_before_gc |
449 | 2 | << " total_counters_before_gc=" << stats.total_counters_before_gc |
450 | 2 | << " total_counters_after_gc=" << stats.total_counters_after_gc |
451 | 2 | << " non_empty_slots=" << stats.non_empty_slots_before_gc |
452 | 2 | << " non_empty_slots_before_gc=" << stats.non_empty_slots_before_gc |
453 | 2 | << " non_empty_slots_after_gc=" << stats.non_empty_slots_after_gc |
454 | 2 | << " max_slot_size=" << stats.max_slot_size_before_gc |
455 | 2 | << " max_slot_size_before_gc=" << stats.max_slot_size_before_gc |
456 | 2 | << " max_slot_size_after_gc=" << stats.max_slot_size_after_gc |
457 | 2 | << " sum_bucket_count=" << stats.sum_bucket_count_before_gc |
458 | 2 | << " sum_bucket_count_before_gc=" << stats.sum_bucket_count_before_gc |
459 | 2 | << " sum_bucket_count_after_gc=" << stats.sum_bucket_count_after_gc |
460 | 2 | << " copied_counters=" << stats.copied_counters |
461 | 2 | << " evicted_counters=" << stats.evicted_counters << " evicted_ratio=" |
462 | 2 | << ratio_or_zero(stats.evicted_counters, stats.total_counters_before_gc) |
463 | 2 | << " compacted_slots=" << stats.compacted_slots << " bucket_reclaim_ratio=" |
464 | 2 | << ratio_or_zero( |
465 | 2 | stats.sum_bucket_count_before_gc >= stats.sum_bucket_count_after_gc |
466 | 2 | ? (stats.sum_bucket_count_before_gc - |
467 | 1 | stats.sum_bucket_count_after_gc) |
468 | 2 | : 0, |
469 | 2 | stats.sum_bucket_count_before_gc) |
470 | 2 | << " gc_elapsed_ms=" << stats.gc_elapsed_ms |
471 | 2 | << " count_calls_total=" << count_calls_total |
472 | 2 | << " existing_hit_total=" << existing_hit_total |
473 | 2 | << " new_counter_total_before=" << new_counter_total_before |
474 | 2 | << " new_counter_total_after=" << new_counter_total_after |
475 | 2 | << " new_counter_delta=" << new_counter_delta |
476 | 2 | << " process_mem_before_mb=" << bytes_to_mb(process_mem_before) |
477 | 2 | << " process_mem_after_mb=" << bytes_to_mb(process_mem_after); |
478 | 2 | } |
479 | 1 | } |
480 | | |
481 | | } // namespace doris |