/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 |