Coverage Report

Created: 2024-11-18 10:37

/root/doris/be/src/runtime/thread_context.h
Line
Count
Source (jump to first uncovered line)
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
#pragma once
19
20
#include <bthread/bthread.h>
21
#include <bthread/types.h>
22
#include <gen_cpp/Types_types.h>
23
#include <stdint.h>
24
25
#include <memory>
26
#include <ostream>
27
#include <string>
28
#include <thread>
29
30
#include "common/exception.h"
31
#include "common/logging.h"
32
#include "gutil/macros.h"
33
#include "runtime/exec_env.h"
34
#include "runtime/memory/mem_tracker_limiter.h"
35
#include "runtime/memory/thread_mem_tracker_mgr.h"
36
#include "runtime/threadlocal.h"
37
#include "util/defer_op.h" // IWYU pragma: keep
38
39
// Used to observe the memory usage of the specified code segment
40
#if defined(USE_MEM_TRACKER) && !defined(UNDEFINED_BEHAVIOR_SANITIZER)
41
// Count a code segment memory (memory malloc - memory free) to int64_t
42
// Usage example: int64_t scope_mem = 0; { SCOPED_MEM_COUNT(&scope_mem); xxx; xxx; }
43
#define SCOPED_MEM_COUNT(scope_mem) \
44
5.17k
    auto VARNAME_LINENUM(scope_mem_count) = doris::ScopeMemCount(scope_mem)
45
46
// Count a code segment memory (memory malloc - memory free) to MemTracker.
47
// Compared to count `scope_mem`, MemTracker is easier to observe from the outside and is thread-safe.
48
// Usage example: std::unique_ptr<MemTracker> tracker = std::make_unique<MemTracker>("first_tracker");
49
//                { SCOPED_CONSUME_MEM_TRACKER(_mem_tracker.get()); xxx; xxx; }
50
// Usually used to record query more detailed memory, including ExecNode operators.
51
#define SCOPED_CONSUME_MEM_TRACKER(mem_tracker) \
52
224
    auto VARNAME_LINENUM(add_mem_consumer) = doris::AddThreadMemTrackerConsumer(mem_tracker)
53
#else
54
#define SCOPED_MEM_COUNT(scope_mem) (void)0
55
#define SCOPED_CONSUME_MEM_TRACKER(mem_tracker) (void)0
56
#endif
57
58
// Used to observe query/load/compaction/e.g. execution thread memory usage and respond when memory exceeds the limit.
59
#if defined(USE_MEM_TRACKER) && !defined(UNDEFINED_BEHAVIOR_SANITIZER)
60
// Attach to query/load/compaction/e.g. when thread starts.
61
// This will save some info about a working thread in the thread context.
62
// And count the memory during thread execution (is actually also the code segment that executes the function)
63
// to specify MemTrackerLimiter, and expect to handle when the memory exceeds the limit, for example cancel query.
64
// Usage is similar to SCOPED_CONSUME_MEM_TRACKER.
65
25
#define SCOPED_ATTACH_TASK(arg1) auto VARNAME_LINENUM(attach_task) = AttachTask(arg1)
66
67
#define SCOPED_ATTACH_TASK_WITH_ID(arg1, arg2, arg3) \
68
1
    auto VARNAME_LINENUM(attach_task) = AttachTask(arg1, arg2, arg3)
69
70
// Switch MemTrackerLimiter for count memory during thread execution.
71
// Usually used after SCOPED_ATTACH_TASK, in order to count the memory of the specified code segment into another
72
// MemTrackerLimiter instead of the MemTrackerLimiter added by the attach task.
73
// Note that, not use it in rpc done.run(), because bthread_setspecific may have errors when UBSAN compiles.
74
#define SCOPED_SWITCH_THREAD_MEM_TRACKER_LIMITER(mem_tracker_limiter) \
75
13
    auto VARNAME_LINENUM(switch_mem_tracker) = SwitchThreadMemTrackerLimiter(mem_tracker_limiter)
76
77
// Usually used to exclude a part of memory in query or load mem tracker and track it to Orphan Mem Tracker.
78
// Note that, not check whether it is currently a Bthread and switch Bthread Local, because this is usually meaningless,
79
// if used in Bthread, and pthread switching is expected, use SwitchThreadMemTrackerLimiter.
80
#define SCOPED_TRACK_MEMORY_TO_UNKNOWN() \
81
48
    auto VARNAME_LINENUM(track_memory_to_unknown) = TrackMemoryToUnknown()
82
#else
83
#define SCOPED_ATTACH_TASK(arg1, ...) (void)0
84
#define SCOPED_ATTACH_TASK_WITH_ID(arg1, arg2, arg3) (void)0
85
#define SCOPED_SWITCH_THREAD_MEM_TRACKER_LIMITER(mem_tracker_limiter) (void)0
86
#define SCOPED_TRACK_MEMORY_TO_UNKNOWN() (void)0
87
#endif
88
89
#define SKIP_MEMORY_CHECK(...)                                    \
90
6
    do {                                                          \
91
6
        doris::thread_context()->skip_memory_check++;             \
92
6
        DEFER({ doris::thread_context()->skip_memory_check--; }); \
93
18
        __VA_ARGS__;                                              \
94
6
    } while (0)
95
96
namespace doris {
97
98
class ThreadContext;
99
class MemTracker;
100
class RuntimeState;
101
102
extern bool k_doris_exit;
103
extern bool k_doris_start;
104
extern bthread_key_t btls_key;
105
106
// Using gcc11 compiles thread_local variable on lower versions of GLIBC will report an error,
107
// see https://github.com/apache/doris/pull/7911
108
//
109
// If we want to avoid this error,
110
// 1. For non-trivial variables in thread_local, such as std::string, you need to store them as pointers to
111
//    ensure that thread_local is trivial, these non-trivial pointers will uniformly call destructors elsewhere.
112
// 2. The default destructor of the thread_local variable cannot be overridden.
113
//
114
// This is difficult to implement. Because the destructor is not overwritten, it means that the outside cannot
115
// be notified when the thread terminates, and the non-trivial pointers in thread_local cannot be released in time.
116
// The func provided by pthread and std::thread doesn't help either.
117
//
118
// So, kudu Class-scoped static thread local implementation was introduced. Solve the above problem by
119
// Thread-scoped thread local + Class-scoped thread local.
120
//
121
// This may look very trick, but it's the best way I can find.
122
//
123
// refer to:
124
//  https://gcc.gnu.org/onlinedocs/gcc-3.3.1/gcc/Thread-Local.html
125
//  https://stackoverflow.com/questions/12049684/
126
//  https://sourceware.org/glibc/wiki/Destructor%20support%20for%20thread_local%20variables
127
//  https://www.jianshu.com/p/756240e837dd
128
//  https://man7.org/linux/man-pages/man3/pthread_tryjoin_np.3.html
129
class ThreadContextPtr {
130
public:
131
    ThreadContextPtr();
132
    // Cannot add destructor `~ThreadContextPtr`, otherwise it will no longer be of type POD, the reason is as above.
133
134
    // TCMalloc hook is triggered during ThreadContext construction, which may lead to deadlock.
135
    bool init = false;
136
137
    DECLARE_STATIC_THREAD_LOCAL(ThreadContext, _ptr);
138
};
139
140
inline thread_local ThreadContextPtr thread_context_ptr;
141
142
// To avoid performance problems caused by frequently calling `bthread_getspecific` to obtain bthread TLS
143
// in tcmalloc hook, cache the key and value of bthread TLS in pthread TLS.
144
inline thread_local ThreadContext* bthread_context;
145
inline thread_local bthread_t bthread_id;
146
147
// The thread context saves some info about a working thread.
148
// 2 required info:
149
//   1. thread_id:   Current thread id, Auto generated.
150
//   2. type:        The type is a enum value indicating which type of task current thread is running.
151
//                   For example: QUERY, LOAD, COMPACTION, ...
152
//   3. task id:     A unique id to identify this task. maybe query id, load job id, etc.
153
//
154
// There may be other optional info to be added later.
155
class ThreadContext {
156
public:
157
70
    ThreadContext() {
158
70
        thread_mem_tracker_mgr.reset(new ThreadMemTrackerMgr());
159
70
        if (ExecEnv::GetInstance()->initialized()) thread_mem_tracker_mgr->init();
160
70
    }
161
162
45
    ~ThreadContext() { thread_context_ptr.init = false; }
163
164
    void attach_task(const TUniqueId& task_id, const TUniqueId& fragment_instance_id,
165
26
                     const std::shared_ptr<MemTrackerLimiter>& mem_tracker) {
166
#ifndef BE_TEST
167
        // will only attach_task at the beginning of the thread function, there should be no duplicate attach_task.
168
        DCHECK(mem_tracker);
169
        // Orphan is thread default tracker.
170
        DCHECK(thread_mem_tracker()->label() == "Orphan")
171
                << ", thread mem tracker label: " << thread_mem_tracker()->label()
172
                << ", attach mem tracker label: " << mem_tracker->label();
173
#endif
174
26
        _task_id = task_id;
175
26
        _fragment_instance_id = fragment_instance_id;
176
26
        thread_mem_tracker_mgr->attach_limiter_tracker(mem_tracker, fragment_instance_id);
177
26
    }
178
179
26
    void detach_task() {
180
26
        _task_id = TUniqueId();
181
26
        _fragment_instance_id = TUniqueId();
182
26
        thread_mem_tracker_mgr->detach_limiter_tracker();
183
26
    }
184
185
0
    const TUniqueId& task_id() const { return _task_id; }
186
0
    const TUniqueId& fragment_instance_id() const { return _fragment_instance_id; }
187
188
15
    std::string get_thread_id() {
189
15
        std::stringstream ss;
190
15
        ss << std::this_thread::get_id();
191
15
        return ss.str();
192
15
    }
193
194
    // After thread_mem_tracker_mgr is initialized, the current thread TCMalloc Hook starts to
195
    // consume/release mem_tracker.
196
    // Note that the use of shared_ptr will cause a crash. The guess is that there is an
197
    // intermediate state during the copy construction of shared_ptr. Shared_ptr is not equal
198
    // to nullptr, but the object it points to is not initialized. At this time, when the memory
199
    // is released somewhere, the TCMalloc hook is triggered to cause the crash.
200
    std::unique_ptr<ThreadMemTrackerMgr> thread_mem_tracker_mgr;
201
167k
    MemTrackerLimiter* thread_mem_tracker() {
202
167k
        return thread_mem_tracker_mgr->limiter_mem_tracker_raw();
203
167k
    }
204
205
2
    void consume_memory(const int64_t size) const {
206
2
        thread_mem_tracker_mgr->consume(size, large_memory_check);
207
2
    }
208
209
    int switch_bthread_local_count = 0;
210
    int skip_memory_check = 0;
211
    bool large_memory_check = true;
212
213
private:
214
    TUniqueId _task_id;
215
    TUniqueId _fragment_instance_id;
216
};
217
218
// Switch thread context from pthread local to bthread local context.
219
// Cache the pointer of bthread local in pthead local,
220
// Avoid calling bthread_getspecific frequently to get bthread local, which has performance problems.
221
class SwitchBthreadLocal {
222
public:
223
263
    static void switch_to_bthread_local() {
224
263
        if (bthread_self() != 0) {
225
            // Very frequent bthread_getspecific will slow, but switch_to_bthread_local is not expected to be much.
226
20
            bthread_context = static_cast<ThreadContext*>(bthread_getspecific(btls_key));
227
20
            if (bthread_context == nullptr) {
228
                // A new bthread starts, two scenarios:
229
                // 1. First call to bthread_getspecific (and before any bthread_setspecific) returns NULL
230
                // 2. There are not enough reusable btls in btls pool.
231
                // else, two scenarios:
232
                // 1. A new bthread starts, but get a reuses btls.
233
                // 2. A pthread switch occurs. Because the pthread switch cannot be accurately identified at the moment.
234
                // So tracker call reset 0 like reuses btls.
235
                // during this period, stop the use of thread_context.
236
15
                thread_context_ptr.init = false;
237
15
                bthread_context = new ThreadContext;
238
                // The brpc server should respond as quickly as possible.
239
15
                bthread_context->thread_mem_tracker_mgr->disable_wait_gc();
240
                // set the data so that next time bthread_getspecific in the thread returns the data.
241
15
                CHECK((0 == bthread_setspecific(btls_key, bthread_context)) || doris::k_doris_exit);
242
15
                thread_context_ptr.init = true;
243
15
            }
244
20
            bthread_id = bthread_self();
245
20
            bthread_context->switch_bthread_local_count++;
246
20
        }
247
263
    }
248
249
    // `switch_to_bthread_local` and `switch_back_pthread_local` should be used in pairs,
250
    // `switch_to_bthread_local` should only be called if `switch_to_bthread_local` returns true
251
263
    static void switch_back_pthread_local() {
252
263
        if (bthread_self() != 0) {
253
20
            if (!bthread_equal(bthread_self(), bthread_id)) {
254
0
                bthread_id = bthread_self();
255
0
                bthread_context = static_cast<ThreadContext*>(bthread_getspecific(btls_key));
256
0
                DCHECK(bthread_context != nullptr);
257
0
            }
258
20
            bthread_context->switch_bthread_local_count--;
259
20
            if (bthread_context->switch_bthread_local_count == 0) {
260
15
                bthread_context = thread_context_ptr._ptr;
261
15
            }
262
20
        }
263
263
    }
264
};
265
266
// Note: All use of thread_context() in bthread requires the use of SwitchBthreadLocal.
267
908k
static ThreadContext* thread_context() {
268
908k
    if (bthread_self() != 0) {
269
        // in bthread
270
220
        if (!bthread_equal(bthread_self(), bthread_id)) {
271
            // bthread switching pthread may be very frequent, remember not to use lock or other time-consuming operations.
272
33
            bthread_id = bthread_self();
273
33
            bthread_context = static_cast<ThreadContext*>(bthread_getspecific(btls_key));
274
            // if nullptr, a new bthread task start and no reusable bthread local,
275
            // or bthread switch pthread but not call switch_to_bthread_local, use pthread local context
276
            // else, bthread switch pthread and called switch_to_bthread_local, use bthread local context.
277
33
            if (bthread_context == nullptr) {
278
28
                bthread_context = thread_context_ptr._ptr;
279
28
            }
280
33
        }
281
220
        return bthread_context;
282
908k
    } else {
283
        // in pthread
284
908k
        return thread_context_ptr._ptr;
285
908k
    }
286
908k
}
Unexecuted instantiation: bloom_filter_predicate_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: runtime_filter_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: remote_file_cache_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: block_column_predicate_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: compaction_delete_bitmap_calculator_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: cumulative_compaction_policy_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: cumulative_compaction_time_series_policy_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: delete_bitmap_calculator_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: delete_handler_test.cpp:_ZN5dorisL14thread_contextEv
delta_writer_test.cpp:_ZN5dorisL14thread_contextEv
Line
Count
Source
267
10.3k
static ThreadContext* thread_context() {
268
10.3k
    if (bthread_self() != 0) {
269
        // in bthread
270
0
        if (!bthread_equal(bthread_self(), bthread_id)) {
271
            // bthread switching pthread may be very frequent, remember not to use lock or other time-consuming operations.
272
0
            bthread_id = bthread_self();
273
0
            bthread_context = static_cast<ThreadContext*>(bthread_getspecific(btls_key));
274
            // if nullptr, a new bthread task start and no reusable bthread local,
275
            // or bthread switch pthread but not call switch_to_bthread_local, use pthread local context
276
            // else, bthread switch pthread and called switch_to_bthread_local, use bthread local context.
277
0
            if (bthread_context == nullptr) {
278
0
                bthread_context = thread_context_ptr._ptr;
279
0
            }
280
0
        }
281
0
        return bthread_context;
282
10.3k
    } else {
283
        // in pthread
284
10.3k
        return thread_context_ptr._ptr;
285
10.3k
    }
286
10.3k
}
Unexecuted instantiation: engine_storage_migration_task_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: file_header_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: lru_cache_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: memtable_flush_executor_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: memtable_sort_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: ordered_data_compaction_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: page_cache_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: primary_key_index_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: row_cursor_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: rowid_conversion_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: beta_rowset_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: rowset_meta_manager_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: bitmap_index_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: bloom_filter_index_reader_writer_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: encoding_info_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: index_compaction_with_deleted_term.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: inverted_index_searcher_cache_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: segcompaction_mow_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: segcompaction_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: single_compaction_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: storage_engine_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: tablet_cooldown_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: tablet_meta_manager_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: tablet_meta_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: tablet_mgr_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: tablet_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: txn_manager_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: snapshot_loader_test.cpp:_ZN5dorisL14thread_contextEv
run_all_tests.cpp:_ZN5dorisL14thread_contextEv
Line
Count
Source
267
1
static ThreadContext* thread_context() {
268
1
    if (bthread_self() != 0) {
269
        // in bthread
270
0
        if (!bthread_equal(bthread_self(), bthread_id)) {
271
            // bthread switching pthread may be very frequent, remember not to use lock or other time-consuming operations.
272
0
            bthread_id = bthread_self();
273
0
            bthread_context = static_cast<ThreadContext*>(bthread_getspecific(btls_key));
274
            // if nullptr, a new bthread task start and no reusable bthread local,
275
            // or bthread switch pthread but not call switch_to_bthread_local, use pthread local context
276
            // else, bthread switch pthread and called switch_to_bthread_local, use bthread local context.
277
0
            if (bthread_context == nullptr) {
278
0
                bthread_context = thread_context_ptr._ptr;
279
0
            }
280
0
        }
281
0
        return bthread_context;
282
1
    } else {
283
        // in pthread
284
1
        return thread_context_ptr._ptr;
285
1
    }
286
1
}
Unexecuted instantiation: key_util_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: parquet_reader_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: parquet_thrift_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: vgeneric_iterators_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: vtablet_sink_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: vertical_compaction_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: vdata_stream_test.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: schema_rowsets_scanner.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: runtime_filter.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: runtime_filter_rpc.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: hdfs_file_system.cpp:_ZN5dorisL14thread_contextEv
local_file_system.cpp:_ZN5dorisL14thread_contextEv
Line
Count
Source
267
2
static ThreadContext* thread_context() {
268
2
    if (bthread_self() != 0) {
269
        // in bthread
270
0
        if (!bthread_equal(bthread_self(), bthread_id)) {
271
            // bthread switching pthread may be very frequent, remember not to use lock or other time-consuming operations.
272
0
            bthread_id = bthread_self();
273
0
            bthread_context = static_cast<ThreadContext*>(bthread_getspecific(btls_key));
274
            // if nullptr, a new bthread task start and no reusable bthread local,
275
            // or bthread switch pthread but not call switch_to_bthread_local, use pthread local context
276
            // else, bthread switch pthread and called switch_to_bthread_local, use bthread local context.
277
0
            if (bthread_context == nullptr) {
278
0
                bthread_context = thread_context_ptr._ptr;
279
0
            }
280
0
        }
281
0
        return bthread_context;
282
2
    } else {
283
        // in pthread
284
2
        return thread_context_ptr._ptr;
285
2
    }
286
2
}
Unexecuted instantiation: file_cache_manager.cpp:_ZN5dorisL14thread_contextEv
stream_load_pipe.cpp:_ZN5dorisL14thread_contextEv
Line
Count
Source
267
183
static ThreadContext* thread_context() {
268
183
    if (bthread_self() != 0) {
269
        // in bthread
270
66
        if (!bthread_equal(bthread_self(), bthread_id)) {
271
            // bthread switching pthread may be very frequent, remember not to use lock or other time-consuming operations.
272
22
            bthread_id = bthread_self();
273
22
            bthread_context = static_cast<ThreadContext*>(bthread_getspecific(btls_key));
274
            // if nullptr, a new bthread task start and no reusable bthread local,
275
            // or bthread switch pthread but not call switch_to_bthread_local, use pthread local context
276
            // else, bthread switch pthread and called switch_to_bthread_local, use bthread local context.
277
22
            if (bthread_context == nullptr) {
278
22
                bthread_context = thread_context_ptr._ptr;
279
22
            }
280
22
        }
281
66
        return bthread_context;
282
117
    } else {
283
        // in pthread
284
117
        return thread_context_ptr._ptr;
285
117
    }
286
183
}
Unexecuted instantiation: daemon.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: base_compaction.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: block_column_predicate.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: compaction.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: cumulative_compaction.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: cumulative_compaction_policy.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: cumulative_compaction_time_series_policy.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: data_dir.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: base_tablet.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: delete_bitmap_calculator.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: delete_handler.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: delta_writer.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: calc_delete_bitmap_executor.cpp:_ZN5dorisL14thread_contextEv
lru_cache.cpp:_ZN5dorisL14thread_contextEv
Line
Count
Source
267
401k
static ThreadContext* thread_context() {
268
401k
    if (bthread_self() != 0) {
269
        // in bthread
270
0
        if (!bthread_equal(bthread_self(), bthread_id)) {
271
            // bthread switching pthread may be very frequent, remember not to use lock or other time-consuming operations.
272
0
            bthread_id = bthread_self();
273
0
            bthread_context = static_cast<ThreadContext*>(bthread_getspecific(btls_key));
274
            // if nullptr, a new bthread task start and no reusable bthread local,
275
            // or bthread switch pthread but not call switch_to_bthread_local, use pthread local context
276
            // else, bthread switch pthread and called switch_to_bthread_local, use bthread local context.
277
0
            if (bthread_context == nullptr) {
278
0
                bthread_context = thread_context_ptr._ptr;
279
0
            }
280
0
        }
281
0
        return bthread_context;
282
401k
    } else {
283
        // in pthread
284
401k
        return thread_context_ptr._ptr;
285
401k
    }
286
401k
}
Unexecuted instantiation: match_predicate.cpp:_ZN5dorisL14thread_contextEv
memtable.cpp:_ZN5dorisL14thread_contextEv
Line
Count
Source
267
12
static ThreadContext* thread_context() {
268
12
    if (bthread_self() != 0) {
269
        // in bthread
270
0
        if (!bthread_equal(bthread_self(), bthread_id)) {
271
            // bthread switching pthread may be very frequent, remember not to use lock or other time-consuming operations.
272
0
            bthread_id = bthread_self();
273
0
            bthread_context = static_cast<ThreadContext*>(bthread_getspecific(btls_key));
274
            // if nullptr, a new bthread task start and no reusable bthread local,
275
            // or bthread switch pthread but not call switch_to_bthread_local, use pthread local context
276
            // else, bthread switch pthread and called switch_to_bthread_local, use bthread local context.
277
0
            if (bthread_context == nullptr) {
278
0
                bthread_context = thread_context_ptr._ptr;
279
0
            }
280
0
        }
281
0
        return bthread_context;
282
12
    } else {
283
        // in pthread
284
12
        return thread_context_ptr._ptr;
285
12
    }
286
12
}
Unexecuted instantiation: memtable_flush_executor.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: merger.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: null_predicate.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: olap_server.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: cold_data_compaction.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: page_cache.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: primary_key_index.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: reader.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: like_column_predicate.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: row_cursor.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: beta_rowset.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: beta_rowset_reader.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: rowset.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: rowset_factory.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: beta_rowset_writer.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: segcompaction.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: bitmap_index_reader.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: bitmap_index_writer.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: bloom_filter_index_reader.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: encoding_info.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: indexed_column_reader.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: indexed_column_writer.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: inverted_index_cache.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: inverted_index_reader.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: ordinal_page_index.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: page_io.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: segment.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: column_reader.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: empty_segment_iterator.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: segment_iterator.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: segment_writer.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: column_writer.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: inverted_index_writer.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: zone_map_index.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: vertical_beta_rowset_writer.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: schema.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: segment_loader.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: single_replica_compaction.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: snapshot_manager.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: storage_engine.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: task_worker_pool.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: tablet.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: full_compaction.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: tablet_manager.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: tablet_meta.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: tablet_meta_manager.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: tablet_schema.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: engine_alter_tablet_task.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: schema_change.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: engine_batch_load_task.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: push_handler.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: engine_checksum_task.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: engine_clone_task.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: engine_index_change_task.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: engine_publish_version_task.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: engine_storage_migration_task.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: index_builder.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: txn_manager.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: wrapper_field.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: buffer_control_block.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: exec_env_init.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: schema_cache.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: fragment_mgr.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: load_channel_mgr.cpp:_ZN5dorisL14thread_contextEv
mem_tracker.cpp:_ZN5dorisL14thread_contextEv
Line
Count
Source
267
4.53k
static ThreadContext* thread_context() {
268
4.53k
    if (bthread_self() != 0) {
269
        // in bthread
270
0
        if (!bthread_equal(bthread_self(), bthread_id)) {
271
            // bthread switching pthread may be very frequent, remember not to use lock or other time-consuming operations.
272
0
            bthread_id = bthread_self();
273
0
            bthread_context = static_cast<ThreadContext*>(bthread_getspecific(btls_key));
274
            // if nullptr, a new bthread task start and no reusable bthread local,
275
            // or bthread switch pthread but not call switch_to_bthread_local, use pthread local context
276
            // else, bthread switch pthread and called switch_to_bthread_local, use bthread local context.
277
0
            if (bthread_context == nullptr) {
278
0
                bthread_context = thread_context_ptr._ptr;
279
0
            }
280
0
        }
281
0
        return bthread_context;
282
4.53k
    } else {
283
        // in pthread
284
4.53k
        return thread_context_ptr._ptr;
285
4.53k
    }
286
4.53k
}
Unexecuted instantiation: mem_tracker_limiter.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: runtime_filter_mgr.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: runtime_state.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: snapshot_loader.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: tablets_channel.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: task_group.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: task_group_manager.cpp:_ZN5dorisL14thread_contextEv
thread_context.cpp:_ZN5dorisL14thread_contextEv
Line
Count
Source
267
498
static ThreadContext* thread_context() {
268
498
    if (bthread_self() != 0) {
269
        // in bthread
270
40
        if (!bthread_equal(bthread_self(), bthread_id)) {
271
            // bthread switching pthread may be very frequent, remember not to use lock or other time-consuming operations.
272
5
            bthread_id = bthread_self();
273
5
            bthread_context = static_cast<ThreadContext*>(bthread_getspecific(btls_key));
274
            // if nullptr, a new bthread task start and no reusable bthread local,
275
            // or bthread switch pthread but not call switch_to_bthread_local, use pthread local context
276
            // else, bthread switch pthread and called switch_to_bthread_local, use bthread local context.
277
5
            if (bthread_context == nullptr) {
278
0
                bthread_context = thread_context_ptr._ptr;
279
0
            }
280
5
        }
281
40
        return bthread_context;
282
458
    } else {
283
        // in pthread
284
458
        return thread_context_ptr._ptr;
285
458
    }
286
498
}
Unexecuted instantiation: http_service.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: internal_service.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: fold_constant_executor.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: point_query_executor.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: obj_lru_cache.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: s3_util.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: check_tablet_segment_action.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: compaction_action.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: download_binlog_action.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: file_cache_action.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: meta_action.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: pad_rowset_action.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: report_action.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: stream_load.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: tablet_migration_action.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: tablets_distribution_action.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: tablets_info_action.cpp:_ZN5dorisL14thread_contextEv
allocator.cpp:_ZN5dorisL14thread_contextEv
Line
Count
Source
267
490k
static ThreadContext* thread_context() {
268
490k
    if (bthread_self() != 0) {
269
        // in bthread
270
114
        if (!bthread_equal(bthread_self(), bthread_id)) {
271
            // bthread switching pthread may be very frequent, remember not to use lock or other time-consuming operations.
272
6
            bthread_id = bthread_self();
273
6
            bthread_context = static_cast<ThreadContext*>(bthread_getspecific(btls_key));
274
            // if nullptr, a new bthread task start and no reusable bthread local,
275
            // or bthread switch pthread but not call switch_to_bthread_local, use pthread local context
276
            // else, bthread switch pthread and called switch_to_bthread_local, use bthread local context.
277
6
            if (bthread_context == nullptr) {
278
6
                bthread_context = thread_context_ptr._ptr;
279
6
            }
280
6
        }
281
114
        return bthread_context;
282
490k
    } else {
283
        // in pthread
284
490k
        return thread_context_ptr._ptr;
285
490k
    }
286
490k
}
Unexecuted instantiation: block.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: block_spill_writer.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: csv_reader.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: new_json_reader.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: vorc_reader.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: vparquet_group_reader.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: vparquet_reader.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: file_meta_cache.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: scan_task_queue.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: scanner_context.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: scanner_scheduler.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: vscanner.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: runtime_filter_consumer.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: vscan_node.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: exec_node.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: new_odbc_scan_node.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: new_odbc_scanner.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: new_jdbc_scan_node.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: new_jdbc_scanner.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: new_es_scan_node.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: new_es_scanner.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: vmeta_scan_node.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: vmeta_scanner.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: new_olap_scan_node.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: new_olap_scanner.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: vhash_join_node.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: vjoin_node_base.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: inner_join_impl.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: left_semi_join_impl.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: left_anti_join_impl.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: left_outer_join_impl.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: full_outer_join_impl.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: right_outer_join_impl.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: cross_join_impl.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: right_semi_join_impl.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: right_anti_join_impl.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: null_aware_left_anti_join_impl.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: vnested_loop_join_node.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: new_file_scan_node.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: vfile_scanner.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: iceberg_reader.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: vaggregation_node.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: vdata_gen_scan_node.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: sorter.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: vset_operation_node.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: vsort_node.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: runtime_predicate.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: heap_sorter.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: vbitmap_predicate.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: vbloom_predicate.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: vexpr_context.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: vmatch_predicate.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: function_array_apply.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: function_array_with_constant.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: function_tokenize.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: in.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: match.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: block_reader.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: vcollect_iterator.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: vertical_block_reader.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: vertical_merge_iterator.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: vgeneric_iterators.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: vdata_stream_recvr.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: vdata_stream_sender.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: data_sink.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: vresult_file_sink.cpp:_ZN5dorisL14thread_contextEv
vtablet_sink.cpp:_ZN5dorisL14thread_contextEv
Line
Count
Source
267
15
static ThreadContext* thread_context() {
268
15
    if (bthread_self() != 0) {
269
        // in bthread
270
0
        if (!bthread_equal(bthread_self(), bthread_id)) {
271
            // bthread switching pthread may be very frequent, remember not to use lock or other time-consuming operations.
272
0
            bthread_id = bthread_self();
273
0
            bthread_context = static_cast<ThreadContext*>(bthread_getspecific(btls_key));
274
            // if nullptr, a new bthread task start and no reusable bthread local,
275
            // or bthread switch pthread but not call switch_to_bthread_local, use pthread local context
276
            // else, bthread switch pthread and called switch_to_bthread_local, use bthread local context.
277
0
            if (bthread_context == nullptr) {
278
0
                bthread_context = thread_context_ptr._ptr;
279
0
            }
280
0
        }
281
0
        return bthread_context;
282
15
    } else {
283
        // in pthread
284
15
        return thread_context_ptr._ptr;
285
15
    }
286
15
}
Unexecuted instantiation: exchange_sink_buffer.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: multi_cast_data_streamer.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: pipeline_fragment_context.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: scan_operator.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: hashjoin_build_sink.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: hashjoin_probe_operator.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: nested_loop_join_build_operator.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: nested_loop_join_probe_operator.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: set_sink_operator.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: set_probe_sink_operator.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: set_source_operator.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: exchange_sink_operator.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: result_file_sink_operator.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: multi_cast_data_stream_source.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: pipeline_task.cpp:_ZN5dorisL14thread_contextEv
Unexecuted instantiation: task_scheduler.cpp:_ZN5dorisL14thread_contextEv
287
288
class ScopeMemCount {
289
public:
290
5.17k
    explicit ScopeMemCount(int64_t* scope_mem) {
291
5.17k
        _scope_mem = scope_mem;
292
5.17k
        thread_context()->thread_mem_tracker_mgr->start_count_scope_mem();
293
5.17k
    }
294
295
5.17k
    ~ScopeMemCount() {
296
5.17k
        *_scope_mem += thread_context()->thread_mem_tracker_mgr->stop_count_scope_mem();
297
5.17k
    }
298
299
private:
300
    int64_t* _scope_mem;
301
};
302
303
class AttachTask {
304
public:
305
    explicit AttachTask(const std::shared_ptr<MemTrackerLimiter>& mem_tracker,
306
                        const TUniqueId& task_id = TUniqueId(),
307
                        const TUniqueId& fragment_instance_id = TUniqueId());
308
309
    explicit AttachTask(RuntimeState* runtime_state);
310
311
    ~AttachTask();
312
};
313
314
class SwitchThreadMemTrackerLimiter {
315
public:
316
13
    explicit SwitchThreadMemTrackerLimiter(const std::shared_ptr<MemTrackerLimiter>& mem_tracker) {
317
13
        SwitchBthreadLocal::switch_to_bthread_local();
318
13
        _old_mem_tracker = thread_context()->thread_mem_tracker_mgr->limiter_mem_tracker();
319
13
        thread_context()->thread_mem_tracker_mgr->attach_limiter_tracker(mem_tracker, TUniqueId());
320
13
    }
321
322
13
    ~SwitchThreadMemTrackerLimiter() {
323
13
        thread_context()->thread_mem_tracker_mgr->detach_limiter_tracker(_old_mem_tracker);
324
13
        SwitchBthreadLocal::switch_back_pthread_local();
325
13
    }
326
327
private:
328
    std::shared_ptr<MemTrackerLimiter> _old_mem_tracker;
329
};
330
331
class TrackMemoryToUnknown {
332
public:
333
48
    explicit TrackMemoryToUnknown() {
334
48
        if (bthread_self() != 0) {
335
22
            _tid = std::this_thread::get_id(); // save pthread id
336
22
        }
337
48
        _old_mem_tracker = thread_context()->thread_mem_tracker_mgr->limiter_mem_tracker();
338
48
        thread_context()->thread_mem_tracker_mgr->attach_limiter_tracker(
339
48
                ExecEnv::GetInstance()->orphan_mem_tracker(), TUniqueId());
340
48
    }
341
342
48
    ~TrackMemoryToUnknown() {
343
48
        if (bthread_self() != 0) {
344
            // make sure pthread is not switch, if switch, mem tracker will be wrong, but not crash in release
345
22
            DCHECK(_tid == std::this_thread::get_id());
346
22
        }
347
48
        thread_context()->thread_mem_tracker_mgr->detach_limiter_tracker(_old_mem_tracker);
348
48
    }
349
350
private:
351
    std::shared_ptr<MemTrackerLimiter> _old_mem_tracker;
352
    std::thread::id _tid;
353
};
354
355
class AddThreadMemTrackerConsumer {
356
public:
357
    // The owner and user of MemTracker are in the same thread, and the raw pointer is faster.
358
    // If mem_tracker is nullptr, do nothing.
359
    explicit AddThreadMemTrackerConsumer(MemTracker* mem_tracker);
360
361
    // The owner and user of MemTracker are in different threads. If mem_tracker is nullptr, do nothing.
362
    explicit AddThreadMemTrackerConsumer(const std::shared_ptr<MemTracker>& mem_tracker);
363
364
    ~AddThreadMemTrackerConsumer();
365
366
private:
367
    std::shared_ptr<MemTracker> _mem_tracker = nullptr; // Avoid mem_tracker being released midway.
368
    bool _need_pop = false;
369
};
370
371
// Basic macros for mem tracker, usually do not need to be modified and used.
372
#ifdef USE_MEM_TRACKER
373
// For the memory that cannot be counted by mem hook, manually count it into the mem tracker, such as mmap.
374
1
#define CONSUME_THREAD_MEM_TRACKER(size) doris::thread_context()->consume_memory(size)
375
1
#define RELEASE_THREAD_MEM_TRACKER(size) doris::thread_context()->consume_memory(-size)
376
377
// used to fix the tracking accuracy of caches.
378
#define THREAD_MEM_TRACKER_TRANSFER_TO(size, tracker)                                        \
379
200k
    doris::thread_context()->thread_mem_tracker_mgr->limiter_mem_tracker_raw()->transfer_to( \
380
200k
            size, tracker)
381
#define THREAD_MEM_TRACKER_TRANSFER_FROM(size, tracker) \
382
200k
    tracker->transfer_to(                               \
383
200k
            size, doris::thread_context()->thread_mem_tracker_mgr->limiter_mem_tracker_raw())
384
385
// Mem Hook to consume thread mem tracker
386
// TODO: In the original design, the MemTracker consume method is called before the memory is allocated.
387
// If the consume succeeds, the memory is actually allocated, otherwise an exception is thrown.
388
// But the statistics of memory through TCMalloc new/delete Hook are after the memory is actually allocated,
389
// which is different from the previous behavior.
390
#define CONSUME_MEM_TRACKER(size)                                                                  \
391
    do {                                                                                           \
392
        if (doris::k_doris_start && doris::thread_context_ptr.init) {                              \
393
            doris::thread_context()->consume_memory(size);                                         \
394
        } else if (doris::k_doris_start && doris::ExecEnv::GetInstance()->initialized()) {         \
395
            doris::ExecEnv::GetInstance()->orphan_mem_tracker_raw()->consume_no_update_peak(size); \
396
        }                                                                                          \
397
    } while (0)
398
#define RELEASE_MEM_TRACKER(size)                                                            \
399
    do {                                                                                     \
400
        if (doris::k_doris_start && doris::thread_context_ptr.init) {                        \
401
            doris::thread_context()->consume_memory(-size);                                  \
402
        } else if (doris::k_doris_start && doris::ExecEnv::GetInstance()->initialized()) {   \
403
            doris::ExecEnv::GetInstance()->orphan_mem_tracker_raw()->consume_no_update_peak( \
404
                    -size);                                                                  \
405
        }                                                                                    \
406
    } while (0)
407
#else
408
#define CONSUME_THREAD_MEM_TRACKER(size) (void)0
409
#define RELEASE_THREAD_MEM_TRACKER(size) (void)0
410
#define THREAD_MEM_TRACKER_TRANSFER_TO(size, tracker) (void)0
411
#define THREAD_MEM_TRACKER_TRANSFER_FROM(size, tracker) (void)0
412
#define CONSUME_MEM_TRACKER(size) (void)0
413
#define RELEASE_MEM_TRACKER(size) (void)0
414
#endif
415
} // namespace doris