be/src/runtime/workload_management/resource_context.h
Line | Count | Source |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | |
18 | | #pragma once |
19 | | |
20 | | #include <cstddef> |
21 | | #include <memory> |
22 | | #include <string> |
23 | | |
24 | | #include "common/factory_creator.h" |
25 | | #include "common/multi_version.h" |
26 | | #include "runtime/runtime_profile.h" |
27 | | #include "runtime/workload_group/workload_group_fwd.h" |
28 | | #include "runtime/workload_management/cpu_context.h" |
29 | | #include "runtime/workload_management/io_context.h" |
30 | | #include "runtime/workload_management/memory_context.h" |
31 | | #include "runtime/workload_management/task_controller.h" |
32 | | |
33 | | namespace doris { |
34 | | |
35 | | class TQueryStatistics; |
36 | | |
37 | | // Every task should have its own resource context. And BE may adjust the resource |
38 | | // context during running. |
39 | | // ResourceContext contains many contexts or controller, the task could implements their |
40 | | // own implementation. |
41 | | class ResourceContext : public std::enable_shared_from_this<ResourceContext> { |
42 | | ENABLE_FACTORY_CREATOR(ResourceContext); |
43 | | |
44 | | public: |
45 | 144k | ResourceContext() { |
46 | | // These all default values, it may be reset. |
47 | 144k | cpu_context_ = CPUContext::create_unique(); |
48 | 144k | memory_context_ = MemoryContext::create_unique(); |
49 | 144k | io_context_ = IOContext::create_unique(); |
50 | 144k | task_controller_ = TaskController::create_unique(); |
51 | | |
52 | 144k | cpu_context_->set_resource_ctx(this); |
53 | 144k | memory_context_->set_resource_ctx(this); |
54 | 144k | io_context_->set_resource_ctx(this); |
55 | 144k | task_controller_->set_resource_ctx(this); |
56 | 144k | _track_if_leak_check_enabled(); |
57 | 144k | } |
58 | | ~ResourceContext(); |
59 | | |
60 | | // Only return the raw pointer to the caller, so that the caller should not save it to other variables. |
61 | 68 | CPUContext* cpu_context() const { return cpu_context_.get(); } |
62 | 1.22M | MemoryContext* memory_context() const { return memory_context_.get(); } |
63 | 4.58k | IOContext* io_context() const { return io_context_.get(); } |
64 | 1.85M | TaskController* task_controller() const { return task_controller_.get(); } |
65 | 19.5k | WorkloadGroupPtr workload_group() const { return _workload_group; } |
66 | | |
67 | 0 | void set_cpu_context(std::unique_ptr<CPUContext> cpu_context) { |
68 | 0 | cpu_context_ = std::move(cpu_context); |
69 | 0 | cpu_context_->set_resource_ctx(this); |
70 | 0 | } |
71 | 0 | void set_memory_context(std::unique_ptr<MemoryContext> memory_context) { |
72 | 0 | memory_context_ = std::move(memory_context); |
73 | 0 | memory_context_->set_resource_ctx(this); |
74 | 0 | } |
75 | 0 | void set_io_context(std::unique_ptr<IOContext> io_context) { |
76 | 0 | io_context_ = std::move(io_context); |
77 | 0 | io_context_->set_resource_ctx(this); |
78 | 0 | } |
79 | 143k | void set_task_controller(std::unique_ptr<TaskController> task_controller) { |
80 | 143k | task_controller_ = std::move(task_controller); |
81 | 143k | task_controller_->set_resource_ctx(this); |
82 | 143k | } |
83 | 102 | void set_workload_group(WorkloadGroupPtr wg) { _workload_group = wg; } |
84 | | |
85 | | void to_thrift_query_statistics(TQueryStatistics* statistics) const; |
86 | | |
87 | 0 | std::string debug_string() { return resource_profile_.get()->pretty_print(); } |
88 | 0 | void refresh_resource_profile() { |
89 | 0 | std::unique_ptr<RuntimeProfile> resource_profile = |
90 | 0 | std::make_unique<RuntimeProfile>("ResourceContext"); |
91 | 0 |
|
92 | 0 | RuntimeProfile* cpu_profile = |
93 | 0 | resource_profile->create_child(cpu_context_->stats_profile()->name(), true, false); |
94 | 0 | cpu_profile->merge(cpu_context_->stats_profile()); |
95 | 0 | RuntimeProfile* memory_profile = resource_profile->create_child( |
96 | 0 | memory_context_->stats_profile()->name(), true, false); |
97 | 0 | memory_profile->merge(memory_context_->stats_profile()); |
98 | 0 | RuntimeProfile* io_profile = |
99 | 0 | resource_profile->create_child(io_context_->stats_profile()->name(), true, false); |
100 | 0 | io_profile->merge(io_context_->stats_profile()); |
101 | 0 |
|
102 | 0 | resource_profile_.set(std::move(resource_profile)); |
103 | 0 | } |
104 | | |
105 | | // Memleak-check mode only (config::enable_graceful_exit_check, where doris_main destroys |
106 | | // everything on exit so that LeakSanitizer can check the heap): returns one line per |
107 | | // resource context that is still alive, at most `max_contexts` of them, or an empty string |
108 | | // if there is none. LeakSanitizer reports a context that was never released only by its |
109 | | // allocation stack, which is the same for every query; the task id printed here tells which |
110 | | // query or load it belonged to. Call it at shutdown, when no context is being created. |
111 | | static std::string describe_live_contexts(size_t max_contexts); |
112 | | |
113 | | // For the end of a graceful exit in memleak-check mode: logs describe_live_contexts() to |
114 | | // be.WARNING and to stderr (be.out, where the LeakSanitizer report follows), or one INFO line |
115 | | // if no context is alive, and returns what it logged. The description is built on a thread |
116 | | // of its own and the caller never touches a context: a pointer to a leaked context left on |
117 | | // the caller's stack would be found by LeakSanitizer, which would then take the context for |
118 | | // referenced and stop reporting it, while the stack of a finished thread is not scanned. |
119 | | static std::string log_live_contexts(); |
120 | | |
121 | | private: |
122 | | // Registers this context for describe_live_contexts() when memleak-check mode is on. |
123 | | void _track_if_leak_check_enabled(); |
124 | | std::string _describe(long references_held_elsewhere) const; |
125 | | |
126 | | // The controller's init value is nullptr, it means the resource context will ignore this controller. |
127 | | std::unique_ptr<CPUContext> cpu_context_ = nullptr; |
128 | | std::unique_ptr<MemoryContext> memory_context_ = nullptr; |
129 | | std::unique_ptr<IOContext> io_context_ = nullptr; |
130 | | std::unique_ptr<TaskController> task_controller_ = nullptr; |
131 | | |
132 | | WorkloadGroupPtr _workload_group = nullptr; |
133 | | MultiVersion<RuntimeProfile> resource_profile_; |
134 | | // Whether this context is registered for describe_live_contexts(). |
135 | | bool _tracked = false; |
136 | | }; |
137 | | |
138 | | } // namespace doris |