Coverage Report

Created: 2026-04-13 22:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/runtime/memory/memory_profile.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 "runtime/memory/memory_profile.h"
19
20
#include "bvar/reducer.h"
21
#include "runtime/exec_env.h"
22
#include "runtime/memory/global_memory_arbitrator.h"
23
#include "runtime/memory/jemalloc_control.h"
24
#include "runtime/memory/mem_tracker_limiter.h"
25
#include "runtime/runtime_profile.h"
26
#include "storage/metadata_adder.h"
27
#include "storage/segment/segment_loader.h"
28
#include "storage/tablet/tablet_schema_cache.h"
29
#include "util/mem_info.h"
30
31
namespace doris {
32
33
static bvar::Adder<int64_t> memory_all_tracked_sum_bytes("memory_all_tracked_sum_bytes");
34
static bvar::Adder<int64_t> memory_global_trackers_sum_bytes("memory_global_trackers_sum_bytes");
35
static bvar::Adder<int64_t> memory_metadata_trackers_sum_bytes(
36
        "memory_metadata_trackers_sum_bytes");
37
static bvar::Adder<int64_t> memory_cache_trackers_sum_bytes("memory_cache_trackers_sum_bytes");
38
static bvar::Adder<int64_t> memory_query_trackers_sum_bytes("memory_query_trackers_sum_bytes");
39
static bvar::Adder<int64_t> memory_load_trackers_sum_bytes("memory_load_trackers_sum_bytes");
40
static bvar::Adder<int64_t> memory_compaction_trackers_sum_bytes(
41
        "memory_compaction_trackers_sum_bytes");
42
static bvar::Adder<int64_t> memory_schema_change_trackers_sum_bytes(
43
        "memory_schema_change_trackers_sum_bytes");
44
static bvar::Adder<int64_t> memory_other_trackers_sum_bytes("memory_other_trackers_sum_bytes");
45
static bvar::Adder<int64_t> memory_reserved_memory_bytes("memory_reserved_memory_bytes");
46
static bvar::Adder<int64_t> memory_all_tasks_memory_bytes("memory_all_tasks_memory_bytes");
47
static bvar::Adder<int64_t> memory_untracked_memory_bytes("memory_untracked_memory_bytes");
48
49
1
MemoryProfile::MemoryProfile() {
50
1
#ifdef ADDRESS_SANITIZER
51
1
    _memory_overview_profile = std::make_unique<RuntimeProfile>("[ASAN]MemoryOverviewSnapshot");
52
#else
53
    _memory_overview_profile = std::make_unique<RuntimeProfile>("MemoryOverviewSnapshot");
54
#endif
55
1
    _global_memory_profile.set(std::make_unique<RuntimeProfile>("GlobalMemorySnapshot"));
56
1
    _metadata_memory_profile.set(std::make_unique<RuntimeProfile>("MetadataMemorySnapshot"));
57
1
    _cache_memory_profile.set(std::make_unique<RuntimeProfile>("CacheMemorySnapshot"));
58
1
    _top_memory_tasks_profile.set(std::make_unique<RuntimeProfile>("TopMemoryTasksSnapshot"));
59
1
    _tasks_memory_profile.set(std::make_unique<RuntimeProfile>("TasksMemorySnapshot"));
60
1
    init_memory_overview_counter();
61
1
}
62
63
1
void MemoryProfile::init_memory_overview_counter() {
64
1
    RuntimeProfile* untracked_memory_profile =
65
1
            _memory_overview_profile->create_child("UntrackedMemory", true, false);
66
1
    RuntimeProfile* tracked_memory_profile =
67
1
            _memory_overview_profile->create_child("TrackedMemory", true, false);
68
1
    RuntimeProfile* tasks_memory_overview_profile =
69
1
            tracked_memory_profile->create_child("TasksMemory", true, false);
70
1
    RuntimeProfile* tasks_memory_overview_details_profile =
71
1
            tasks_memory_overview_profile->create_child("Details", true, false);
72
73
1
    RuntimeProfile* memtable_overview_profile =
74
1
            tracked_memory_profile->create_child("MemtableMemory", true, false);
75
76
1
    RuntimeProfile* global_memory_overview_profile =
77
1
            tracked_memory_profile->create_child("GlobalMemory", true, false);
78
79
1
    RuntimeProfile* jvm_memory_overview_profile =
80
1
            tracked_memory_profile->create_child("JvmMemory", true, false);
81
1
    RuntimeProfile* metadata_memory_overview_profile =
82
1
            tracked_memory_profile->create_child("MetadataMemory", true, false);
83
1
    RuntimeProfile* cache_memory_overview_profile =
84
1
            tracked_memory_profile->create_child("CacheMemory", true, false);
85
1
    RuntimeProfile* jemalloc_memory_profile =
86
1
            tracked_memory_profile->create_child("JemallocMemory", true, false);
87
1
    RuntimeProfile* jemalloc_memory_details_profile =
88
1
            jemalloc_memory_profile->create_child("Details", true, false);
89
90
    // 1 add process memory counter
91
1
    _process_physical_memory_usage_counter = _memory_overview_profile->AddHighWaterMarkCounter(
92
1
            "PhysicalMemory(VmRSS)", TUnit::BYTES);
93
1
    _process_virtual_memory_usage_counter = _memory_overview_profile->AddHighWaterMarkCounter(
94
1
            "VirtualMemory(VmSize)", TUnit::BYTES);
95
96
    // 2 add untracked/tracked memory counter
97
1
    _untracked_memory_usage_counter =
98
1
            untracked_memory_profile->AddHighWaterMarkCounter("Memory", TUnit::BYTES);
99
1
    _tracked_memory_usage_counter =
100
1
            tracked_memory_profile->AddHighWaterMarkCounter("Memory", TUnit::BYTES);
101
102
    // 3 add Jemalloc memory counter
103
1
    _jemalloc_memory_usage_counter =
104
1
            jemalloc_memory_profile->AddHighWaterMarkCounter("Memory", TUnit::BYTES);
105
1
    _jemalloc_cache_usage_counter =
106
1
            jemalloc_memory_details_profile->AddHighWaterMarkCounter("Cache", TUnit::BYTES);
107
1
    _jemalloc_metadata_usage_counter =
108
1
            jemalloc_memory_details_profile->AddHighWaterMarkCounter("Metadata", TUnit::BYTES);
109
110
    // 4 add global/metadata/cache/Jvm memory counter
111
1
    _global_usage_counter =
112
1
            global_memory_overview_profile->AddHighWaterMarkCounter("Memory", TUnit::BYTES);
113
1
    _metadata_usage_counter =
114
1
            metadata_memory_overview_profile->AddHighWaterMarkCounter("Memory", TUnit::BYTES);
115
1
    _cache_usage_counter =
116
1
            cache_memory_overview_profile->AddHighWaterMarkCounter("Memory", TUnit::BYTES);
117
1
    _jvm_heap_memory_usage_counter =
118
1
            jvm_memory_overview_profile->AddHighWaterMarkCounter("HeapMemory", TUnit::BYTES);
119
1
    _jvm_non_heap_memory_usage_counter =
120
1
            jvm_memory_overview_profile->AddHighWaterMarkCounter("NonHeapMemory", TUnit::BYTES);
121
122
    // 5 add tasks memory counter
123
1
    _tasks_memory_usage_counter =
124
1
            tasks_memory_overview_profile->AddHighWaterMarkCounter("Memory", TUnit::BYTES);
125
    // Reserved memory is the sum of all task reserved memory, is duplicated with all task memory counter.
126
1
    _reserved_memory_usage_counter = tasks_memory_overview_profile->AddHighWaterMarkCounter(
127
1
            "ReservedMemory", TUnit::BYTES, "Memory", 1);
128
129
    // 6 add memtable memory counter
130
1
    _memtable_memory_usage_counter =
131
1
            memtable_overview_profile->AddHighWaterMarkCounter("MemtableMemory", TUnit::BYTES);
132
1
    _query_usage_counter =
133
1
            tasks_memory_overview_details_profile->AddHighWaterMarkCounter("Query", TUnit::BYTES);
134
1
    _load_usage_counter =
135
1
            tasks_memory_overview_details_profile->AddHighWaterMarkCounter("Load", TUnit::BYTES);
136
1
    _compaction_usage_counter = tasks_memory_overview_details_profile->AddHighWaterMarkCounter(
137
1
            "Compaction", TUnit::BYTES);
138
1
    _schema_change_usage_counter = tasks_memory_overview_details_profile->AddHighWaterMarkCounter(
139
1
            "SchemaChange", TUnit::BYTES);
140
1
    _other_usage_counter =
141
1
            tasks_memory_overview_details_profile->AddHighWaterMarkCounter("Other", TUnit::BYTES);
142
1
}
143
144
0
void MemoryProfile::refresh_memory_overview_profile() {
145
    // 1 create profile
146
0
    std::unique_ptr<RuntimeProfile> global_memory_profile =
147
0
            std::make_unique<RuntimeProfile>("GlobalMemorySnapshot");
148
0
    std::unique_ptr<RuntimeProfile> metadata_memory_profile =
149
0
            std::make_unique<RuntimeProfile>("MetadataMemorySnapshot");
150
0
    std::unique_ptr<RuntimeProfile> cache_memory_profile =
151
0
            std::make_unique<RuntimeProfile>("CacheMemorySnapshot");
152
0
    std::unique_ptr<RuntimeProfile> top_memory_tasks_profile =
153
0
            std::make_unique<RuntimeProfile>("TopMemoryTasksSnapshot");
154
155
    // 2 refresh process memory counter
156
0
    COUNTER_SET(_process_physical_memory_usage_counter,
157
0
                PerfCounters::get_vm_rss()); // from /proc VmRSS VmHWM
158
0
    COUNTER_SET(_process_virtual_memory_usage_counter,
159
0
                PerfCounters::get_vm_size()); // from /proc VmSize VmPeak
160
161
    // 2 refresh metadata memory tracker
162
0
    ExecEnv::GetInstance()->tablets_no_cache_mem_tracker()->set_consumption(
163
0
            MetadataAdder<TabletMeta>::get_all_tablets_size() -
164
0
            TabletSchemaCache::instance()->value_mem_consumption());
165
0
    ExecEnv::GetInstance()->rowsets_no_cache_mem_tracker()->set_consumption(
166
0
            MetadataAdder<RowsetMeta>::get_all_rowsets_size());
167
0
    ExecEnv::GetInstance()->segments_no_cache_mem_tracker()->set_consumption(
168
0
            MetadataAdder<segment_v2::Segment>::get_all_segments_estimate_size() -
169
0
            SegmentLoader::instance()->cache_mem_usage());
170
171
    // 4 refresh tracked memory counter
172
0
    std::unordered_map<MemTrackerLimiter::Type, int64_t> type_mem_sum = {
173
0
            {MemTrackerLimiter::Type::GLOBAL, 0},        {MemTrackerLimiter::Type::QUERY, 0},
174
0
            {MemTrackerLimiter::Type::LOAD, 0},          {MemTrackerLimiter::Type::COMPACTION, 0},
175
0
            {MemTrackerLimiter::Type::SCHEMA_CHANGE, 0}, {MemTrackerLimiter::Type::METADATA, 0},
176
0
            {MemTrackerLimiter::Type::CACHE, 0},         {MemTrackerLimiter::Type::OTHER, 0}};
177
    // always ExecEnv::ready(), because Daemon::_stop_background_threads_latch
178
0
    for (auto& group : ExecEnv::GetInstance()->mem_tracker_limiter_pool) {
179
0
        std::lock_guard<std::mutex> l(group.group_lock);
180
0
        for (auto trackerWptr : group.trackers) {
181
0
            auto tracker = trackerWptr.lock();
182
0
            if (tracker != nullptr) {
183
0
                type_mem_sum[tracker->type()] += tracker->consumption();
184
0
            }
185
0
        }
186
0
    }
187
188
0
    int64_t all_tracked_mem_sum = 0;
189
0
    int64_t tasks_trackers_mem_sum = 0;
190
0
    for (auto it : type_mem_sum) {
191
0
        all_tracked_mem_sum += it.second;
192
0
        switch (it.first) {
193
0
        case MemTrackerLimiter::Type::GLOBAL:
194
0
            COUNTER_SET(_global_usage_counter, it.second);
195
0
            memory_global_trackers_sum_bytes
196
0
                    << it.second - memory_global_trackers_sum_bytes.get_value();
197
0
            break;
198
0
        case MemTrackerLimiter::Type::QUERY:
199
0
            COUNTER_SET(_query_usage_counter, it.second);
200
0
            tasks_trackers_mem_sum += it.second;
201
0
            memory_query_trackers_sum_bytes
202
0
                    << it.second - memory_query_trackers_sum_bytes.get_value();
203
0
            break;
204
0
        case MemTrackerLimiter::Type::LOAD:
205
0
            COUNTER_SET(_load_usage_counter, it.second);
206
0
            tasks_trackers_mem_sum += it.second;
207
0
            memory_load_trackers_sum_bytes
208
0
                    << it.second - memory_load_trackers_sum_bytes.get_value();
209
0
            break;
210
0
        case MemTrackerLimiter::Type::COMPACTION:
211
0
            COUNTER_SET(_compaction_usage_counter, it.second);
212
0
            tasks_trackers_mem_sum += it.second;
213
0
            memory_compaction_trackers_sum_bytes
214
0
                    << it.second - memory_compaction_trackers_sum_bytes.get_value();
215
0
            break;
216
0
        case MemTrackerLimiter::Type::SCHEMA_CHANGE:
217
0
            COUNTER_SET(_schema_change_usage_counter, it.second);
218
0
            tasks_trackers_mem_sum += it.second;
219
0
            memory_schema_change_trackers_sum_bytes
220
0
                    << it.second - memory_schema_change_trackers_sum_bytes.get_value();
221
0
            break;
222
0
        case MemTrackerLimiter::Type::METADATA:
223
0
            COUNTER_SET(_metadata_usage_counter, it.second);
224
0
            memory_metadata_trackers_sum_bytes
225
0
                    << it.second - memory_metadata_trackers_sum_bytes.get_value();
226
0
            break;
227
0
        case MemTrackerLimiter::Type::CACHE:
228
0
            COUNTER_SET(_cache_usage_counter, it.second);
229
0
            memory_cache_trackers_sum_bytes
230
0
                    << it.second - memory_cache_trackers_sum_bytes.get_value();
231
0
            break;
232
0
        case MemTrackerLimiter::Type::OTHER:
233
0
            COUNTER_SET(_other_usage_counter, it.second);
234
0
            tasks_trackers_mem_sum += it.second;
235
0
            memory_other_trackers_sum_bytes
236
0
                    << it.second - memory_other_trackers_sum_bytes.get_value();
237
0
        }
238
0
    }
239
240
0
    MemTrackerLimiter::make_type_trackers_profile(global_memory_profile.get(),
241
0
                                                  MemTrackerLimiter::Type::GLOBAL);
242
0
    MemTrackerLimiter::make_type_trackers_profile(metadata_memory_profile.get(),
243
0
                                                  MemTrackerLimiter::Type::METADATA);
244
0
    MemTrackerLimiter::make_type_trackers_profile(cache_memory_profile.get(),
245
0
                                                  MemTrackerLimiter::Type::CACHE);
246
247
0
    MemTrackerLimiter::make_top_consumption_tasks_tracker_profile(top_memory_tasks_profile.get(),
248
0
                                                                  15);
249
250
0
    COUNTER_SET(_tasks_memory_usage_counter, tasks_trackers_mem_sum);
251
0
    memory_all_tasks_memory_bytes << tasks_trackers_mem_sum -
252
0
                                             memory_all_tasks_memory_bytes.get_value();
253
254
0
    COUNTER_SET(_reserved_memory_usage_counter, GlobalMemoryArbitrator::process_reserved_memory());
255
0
    memory_reserved_memory_bytes << GlobalMemoryArbitrator::process_reserved_memory() -
256
0
                                            memory_reserved_memory_bytes.get_value();
257
258
0
    all_tracked_mem_sum += JemallocControl::je_cache_bytes();
259
0
    COUNTER_SET(_jemalloc_cache_usage_counter,
260
0
                static_cast<int64_t>(JemallocControl::je_cache_bytes()));
261
0
    all_tracked_mem_sum += JemallocControl::je_metadata_mem();
262
0
    COUNTER_SET(_jemalloc_metadata_usage_counter,
263
0
                static_cast<int64_t>(JemallocControl::je_metadata_mem()));
264
0
    COUNTER_SET(_jemalloc_memory_usage_counter,
265
0
                _jemalloc_cache_usage_counter->current_value() +
266
0
                        _jemalloc_metadata_usage_counter->current_value());
267
0
    int64_t jvm_heap_bytes = 0;
268
0
    int64_t jvm_non_heap_bytes = 0;
269
    // JvmMetrics only inited when enable_java_support == true, or it is nullptr
270
0
    if (DorisMetrics::instance()->jvm_metrics() != nullptr) {
271
0
        DorisMetrics::instance()->jvm_metrics()->update();
272
0
        jvm_heap_bytes =
273
0
                DorisMetrics::instance()->jvm_metrics()->jvm_heap_size_bytes_committed->value();
274
0
        jvm_non_heap_bytes =
275
0
                DorisMetrics::instance()->jvm_metrics()->jvm_non_heap_size_bytes_committed->value();
276
0
    }
277
278
0
    all_tracked_mem_sum += jvm_heap_bytes + jvm_non_heap_bytes;
279
0
    COUNTER_SET(_jvm_heap_memory_usage_counter, jvm_heap_bytes);
280
0
    COUNTER_SET(_jvm_non_heap_memory_usage_counter, jvm_non_heap_bytes);
281
282
    // Memtable memory is not included in the memory the load tasks. Because actually it is a buffer.
283
0
    COUNTER_SET(_memtable_memory_usage_counter,
284
0
                ExecEnv::GetInstance()->memtable_memory_limiter()->mem_tracker()->consumption());
285
0
    all_tracked_mem_sum +=
286
0
            ExecEnv::GetInstance()->memtable_memory_limiter()->mem_tracker()->consumption();
287
288
0
    COUNTER_SET(_tracked_memory_usage_counter, all_tracked_mem_sum);
289
0
    memory_all_tracked_sum_bytes << all_tracked_mem_sum - memory_all_tracked_sum_bytes.get_value();
290
291
    // 5 refresh untracked memory counter
292
0
    int64_t untracked_memory =
293
0
            _process_physical_memory_usage_counter->current_value() - all_tracked_mem_sum;
294
0
    COUNTER_SET(_untracked_memory_usage_counter, untracked_memory);
295
0
    memory_untracked_memory_bytes << untracked_memory - memory_untracked_memory_bytes.get_value();
296
297
    // 6. reset profile
298
0
    _global_memory_profile.set(std::move(global_memory_profile));
299
0
    _metadata_memory_profile.set(std::move(metadata_memory_profile));
300
0
    _cache_memory_profile.set(std::move(cache_memory_profile));
301
0
    _top_memory_tasks_profile.set(std::move(top_memory_tasks_profile));
302
0
}
303
304
0
void MemoryProfile::refresh_tasks_memory_profile() {
305
0
    std::unique_ptr<RuntimeProfile> tasks_memory_profile =
306
0
            std::make_unique<RuntimeProfile>("AllTasksMemorySnapshot");
307
0
    MemTrackerLimiter::make_all_tasks_tracker_profile(tasks_memory_profile.get());
308
0
    _tasks_memory_profile.set(std::move(tasks_memory_profile));
309
0
}
310
311
0
void MemoryProfile::make_memory_profile(RuntimeProfile* profile) const {
312
0
    RuntimeProfile* memory_profile_snapshot = profile->create_child("MemoryProfile", true, false);
313
314
0
    RuntimeProfile* memory_overview_profile =
315
0
            memory_profile_snapshot->create_child(_memory_overview_profile->name(), true, false);
316
0
    memory_overview_profile->merge(_memory_overview_profile.get());
317
318
0
    auto global_memory_version_ptr = _global_memory_profile.get();
319
0
    RuntimeProfile* global_memory_profile =
320
0
            memory_profile_snapshot->create_child(global_memory_version_ptr->name(), true, false);
321
0
    global_memory_profile->merge(global_memory_version_ptr.get());
322
323
0
    auto metadata_memory_version_ptr = _metadata_memory_profile.get();
324
0
    RuntimeProfile* metadata_memory_profile =
325
0
            memory_profile_snapshot->create_child(metadata_memory_version_ptr->name(), true, false);
326
0
    metadata_memory_profile->merge(metadata_memory_version_ptr.get());
327
328
0
    auto cache_memory_version_ptr = _cache_memory_profile.get();
329
0
    RuntimeProfile* cache_memory_profile =
330
0
            memory_profile_snapshot->create_child(cache_memory_version_ptr->name(), true, false);
331
0
    cache_memory_profile->merge(cache_memory_version_ptr.get());
332
333
0
    auto top_memory_tasks_version_ptr = _top_memory_tasks_profile.get();
334
0
    RuntimeProfile* top_memory_tasks_profile = memory_profile_snapshot->create_child(
335
0
            top_memory_tasks_version_ptr->name(), true, false);
336
0
    top_memory_tasks_profile->merge(top_memory_tasks_version_ptr.get());
337
338
0
    auto tasks_memory_version_ptr = _tasks_memory_profile.get();
339
0
    RuntimeProfile* tasks_memory_profile =
340
0
            memory_profile_snapshot->create_child(tasks_memory_version_ptr->name(), true, false);
341
0
    tasks_memory_profile->merge(tasks_memory_version_ptr.get());
342
0
}
343
344
0
int64_t MemoryProfile::query_current_usage() {
345
0
    return memory_query_trackers_sum_bytes.get_value();
346
0
}
347
1
int64_t MemoryProfile::load_current_usage() {
348
1
    return memory_load_trackers_sum_bytes.get_value();
349
1
}
350
0
int64_t MemoryProfile::compaction_current_usage() {
351
0
    return memory_compaction_trackers_sum_bytes.get_value();
352
0
}
353
0
int64_t MemoryProfile::schema_change_current_usage() {
354
0
    return memory_schema_change_trackers_sum_bytes.get_value();
355
0
}
356
0
int64_t MemoryProfile::other_current_usage() {
357
0
    return memory_other_trackers_sum_bytes.get_value();
358
0
}
359
360
4
std::string MemoryProfile::process_memory_detail_str() const {
361
4
    return fmt::format("Process Memory Summary: {}\n, {}\n, {}\n, {}\n, {}\n, {}\n",
362
4
                       GlobalMemoryArbitrator::process_mem_log_str(),
363
4
                       print_memory_overview_profile(), print_global_memory_profile(),
364
4
                       print_metadata_memory_profile(), print_cache_memory_profile(),
365
4
                       print_top_memory_tasks_profile());
366
4
}
367
368
0
void MemoryProfile::print_log_process_usage() {
369
0
    if (_enable_print_log_process_usage) {
370
0
        _enable_print_log_process_usage = false;
371
0
        auto log_str = process_memory_detail_str();
372
        LOG_LONG_STRING(INFO, log_str);
373
0
    }
374
0
}
375
376
} // namespace doris