Coverage Report

Created: 2026-04-18 15:51

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
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.3k
    for (const auto& [_, partition_to_value] : snapshot) {
68
17.3k
        entries += partition_to_value.size();
69
17.3k
    }
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.44M
void TabletHotspot::count(const BaseTablet& tablet) {
88
1.44M
    count(tablet.tablet_id(), tablet.table_id(), tablet.index_id(), tablet.partition_id());
89
1.44M
}
90
91
void TabletHotspot::count(int64_t tablet_id, int64_t table_id, int64_t index_id,
92
1.43M
                          int64_t partition_id) {
93
1.43M
    const uint64_t count_calls_total =
94
1.43M
            _count_calls_total.fetch_add(1, std::memory_order_relaxed) + 1;
95
96
1.43M
    size_t slot_idx = tablet_id % s_slot_size;
97
1.43M
    auto& slot = _tablets_hotspot[slot_idx];
98
1.43M
    bool should_log_new_counter = false;
99
1.43M
    uint64_t new_counter_total = 0;
100
1.43M
    {
101
1.43M
        std::lock_guard lock(slot.mtx);
102
1.43M
        HotspotCounterPtr counter;
103
1.43M
        if (auto iter = slot.map.find(tablet_id); iter == slot.map.end()) {
104
91.2k
            counter = std::make_shared<HotspotCounter>(table_id, index_id, partition_id);
105
91.2k
            slot.map.insert(std::make_pair(tablet_id, counter));
106
91.2k
            new_counter_total = _new_counter_total.fetch_add(1, std::memory_order_relaxed) + 1;
107
91.2k
            should_log_new_counter = (new_counter_total % kNewCounterLogInterval == 0);
108
1.34M
        } else {
109
1.34M
            counter = iter->second;
110
1.34M
            _existing_hit_total.fetch_add(1, std::memory_order_relaxed);
111
1.34M
        }
112
1.43M
        counter->last_access_time = std::chrono::system_clock::now();
113
1.43M
        counter->cur_counter.fetch_add(1, std::memory_order_relaxed);
114
1.43M
    }
115
116
1.43M
    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.43M
    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.43M
}
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
51
    for (const auto& [key, partition_to_value] : hot_partition) {
154
51
        THotTableMessage msg;
155
51
        msg.table_id = key.first;
156
51
        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
50
        msg.__isset.hot_partitions = !msg.hot_partitions.empty();
191
50
        hot_tables->push_back(std::move(msg));
192
50
    }
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
84.5k
        for (auto& [_, counter] : map.map) {
223
84.5k
            if (counter->qpd() != 0) {
224
84.5k
                auto& hot_partition = day_hot_partitions[std::make_pair(
225
84.5k
                        counter->table_id, counter->index_id)][counter->partition_id];
226
84.5k
                hot_partition.qpd = std::max(hot_partition.qpd, counter->qpd());
227
84.5k
                hot_partition.qpw = std::max(hot_partition.qpw, counter->qpw());
228
84.5k
                hot_partition.last_access_time =
229
84.5k
                        std::max<int64_t>(hot_partition.last_access_time,
230
84.5k
                                          std::chrono::duration_cast<std::chrono::seconds>(
231
84.5k
                                                  counter->last_access_time.time_since_epoch())
232
84.5k
                                                  .count());
233
84.5k
            } 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
84.5k
        }
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
85.0k
void HotspotCounter::make_dot_point() {
293
85.0k
    uint64_t value = cur_counter.exchange(0, std::memory_order_acq_rel);
294
85.0k
    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
85.0k
    } else if (history_counters.size() < day_counters_size) {
301
85.0k
        week_history_counter += value;
302
85.0k
        day_history_counter += value;
303
85.0k
    } 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
85.0k
    history_counters.push_front(value);
309
85.0k
}
310
311
169k
uint64_t HotspotCounter::qpd() {
312
169k
    return day_history_counter + cur_counter.load();
313
169k
}
314
315
84.5k
uint64_t HotspotCounter::qpw() {
316
84.5k
    return week_history_counter + cur_counter.load();
317
84.5k
}
318
319
85.0k
bool TabletHotspot::is_gc_eligible(const HotspotCounter& counter, SystemTimePoint now) {
320
85.0k
    const auto week_window = std::chrono::seconds((HotspotCounter::week_counters_size + 1) *
321
85.0k
                                                  HotspotCounter::time_interval);
322
85.0k
    return counter.last_access_time < now - week_window &&
323
85.0k
           counter.cur_counter.load(std::memory_order_relaxed) == 0 &&
324
85.0k
           counter.day_history_counter.load(std::memory_order_relaxed) == 0 &&
325
85.0k
           counter.week_history_counter.load(std::memory_order_relaxed) == 0;
326
85.0k
}
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
85.0k
            for (auto& [_, counter] : slot.map) {
351
85.0k
                counters.push_back(counter);
352
85.0k
            }
353
6.14k
        }
354
6.14k
        stats.copied_counters += counters.size();
355
6.14k
        std::for_each(counters.begin(), counters.end(),
356
85.0k
                      [](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
91.1k
            for (auto iter = slot.map.begin(); iter != slot.map.end();) {
366
85.0k
                if (is_gc_eligible(*iter->second, now)) {
367
259
                    iter = slot.map.erase(iter);
368
259
                    ++erased_count;
369
84.7k
                } else {
370
84.7k
                    ++iter;
371
84.7k
                }
372
85.0k
            }
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