1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #ifndef API_CORE_PERF_CPU_PERF_SCOPE_H
16 #define API_CORE_PERF_CPU_PERF_SCOPE_H
17
18 #if (CORE_PERF_ENABLED == 1)
19
20 #include <base/containers/string.h>
21 #include <base/containers/string_view.h>
22 #include <base/namespace.h>
23 #include <core/implementation_uids.h>
24 #include <core/namespace.h>
25 #include <core/perf/intf_performance_data_manager.h>
26 #include <core/perf/intf_performance_trace.h>
27 #include <core/plugin/intf_class_register.h>
28
CORE_BEGIN_NAMESPACE()29 CORE_BEGIN_NAMESPACE()
30
31 // Placeholder interface for disabled paths, disabled path uses static typing so template deducation so basic compiler
32 // can strip the calls.
33 class NullIPerformanceTrace {
34 inline constexpr uintptr_t BeginEvent(const IPerformanceDataManager::Event& location, BASE_NS::string_view text)
35 {
36 return 0;
37 }
38 inline constexpr void EndEvent(uintptr_t eventTag) {}
39 inline constexpr void Message(const char* message, int callstack) {}
40 inline constexpr void Message(const char* message, size_t len, int callstack) {}
41 inline constexpr void AppInfo(const char* name, size_t len) {}
42 inline constexpr void Plot(const char* name, int64_t value) {}
43 inline constexpr void FrameBegin(const char* name) {}
44 inline constexpr void FrameEnd(const char* name) {}
45 inline constexpr void MemAllocNamed(const void* ptr, size_t size, bool secure, const char* name) {}
46 inline constexpr void MemFreeNamed(const void* ptr, bool secure, const char* name) {}
47 };
48
49 // Setups two code paths, one enabled and one disabled
50 constexpr int PROFILER_ENABLED = 1;
51 constexpr int PROFILER_DISABLED = 0;
52
53 constexpr uint32_t CORE_PROFILER_DEFAULT_COLOR { 0xff0000 };
54
55 // Use template specialisation to handle two code paths for enabled and disabled
56 template<int>
57 inline auto* GetTracer();
58
59 template<>
60 inline auto* GetTracer<PROFILER_ENABLED>()
61 {
62 static IPerformanceTrace* tracer { nullptr };
63 if (!tracer) {
64 if (auto* inst = GetInstance<IPerformanceDataManagerFactory>(UID_PERFORMANCE_FACTORY)) {
65 tracer = inst->GetFirstPerformanceTrace();
66 }
67 }
68
69 return tracer;
70 }
71 template<>
72 inline auto* GetTracer<PROFILER_DISABLED>()
73 {
74 static NullIPerformanceTrace tracer;
75 return &tracer;
76 }
77
78 // Use template specialisation to handle two code paths for enabled and disabled
79 template<int>
80 class CpuPerfScopeI;
81
82 template<>
83 class CpuPerfScopeI<PROFILER_DISABLED> final {
84 public:
CpuPerfScopeI(const BASE_NS::string_view category,const BASE_NS::string_view subCategory,const BASE_NS::string_view name,const IPerformanceDataManager::Event & location)85 inline CpuPerfScopeI(const BASE_NS::string_view category, const BASE_NS::string_view subCategory,
86 const BASE_NS::string_view name, const IPerformanceDataManager::Event& location)
87 {}
Stop()88 inline void Stop() {}
89 };
90
91 template<>
92 class CpuPerfScopeI<PROFILER_ENABLED> final {
93 public:
CpuPerfScopeI(const BASE_NS::string_view category,const BASE_NS::string_view subCategory,const BASE_NS::string_view name,const IPerformanceDataManager::Event & location)94 CpuPerfScopeI(const BASE_NS::string_view category, const BASE_NS::string_view subCategory,
95 const BASE_NS::string_view name, const IPerformanceDataManager::Event& location)
96 : subCategory_(subCategory), name_(name)
97 {
98 if (auto* inst = GetInstance<IPerformanceDataManagerFactory>(UID_PERFORMANCE_FACTORY); inst) {
99 manager_ = inst->Get(category);
100 }
101
102 if (manager_) {
103 timerName_ = manager_->BeginTimer();
104 if (auto tracer = GetTracer<PROFILER_ENABLED>()) {
105 token_ = tracer->BeginEvent(location, name);
106 }
107 }
108 }
~CpuPerfScopeI()109 ~CpuPerfScopeI()
110 {
111 Stop();
112 }
Stop()113 inline void Stop()
114 {
115 if (manager_) {
116 if (auto tracer = GetTracer<PROFILER_ENABLED>()) {
117 tracer->EndEvent(token_);
118 }
119 manager_->UpdateData(subCategory_, name_, manager_->EndTimer(timerName_));
120 manager_ = nullptr;
121 }
122 }
123
124 protected:
125 IPerformanceDataManager* manager_ { nullptr };
126 IPerformanceDataManager::TimerHandle timerName_ {};
127 uintptr_t token_ {};
128 BASE_NS::string subCategory_;
129 BASE_NS::string name_;
130 };
131 using CpuPerfScope = CpuPerfScopeI<PROFILER_ENABLED>;
132
133 template<int N>
134 struct PerformanceTraceSubsystem;
135
136 template<>
137 struct PerformanceTraceSubsystem<1> {
138 static constexpr bool IsEnabled()
139 {
140 return true;
141 }
142 };
143
144 using PROFILER_SUBSYSTEM_DEFAULT = PerformanceTraceSubsystem<1>;
145
146 template<int N>
147 struct PerformanceTraceSeverity {
148 static constexpr bool IsEnabled()
149 {
150 if constexpr (N <= 1000) {
151 return true;
152 } else {
153 return false;
154 }
155 }
156 };
157
158 using PROFILER_DEFAULT = PerformanceTraceSeverity<1000>; // 1000: size
159 using PROFILER_TRACE = PerformanceTraceSeverity<2000>; // 2000: size
160
161 template<int z = 0, typename x = PROFILER_SUBSYSTEM_DEFAULT, typename y = PROFILER_DEFAULT>
162 inline constexpr bool PerformanceTraceEnabled()
163 {
164 constexpr bool a = x::IsEnabled() && y::IsEnabled() ? true : false;
165 return a;
166 }
167
168 template<>
169 inline constexpr bool PerformanceTraceEnabled<0, void, void>()
170 {
171 return PerformanceTraceEnabled<0, PROFILER_SUBSYSTEM_DEFAULT, PROFILER_DEFAULT>();
172 }
173
174 CORE_END_NAMESPACE()
175
176 // Helper to concatenate macro values.
177 #define CORE_CONCAT_NOEXP(value0, value1) value0##value1
178 #define CORE_CONCAT(value0, value1) CORE_CONCAT_NOEXP(value0, value1)
179
180 #define CORE_PROFILER_TOKEN(arg) arg
181 #define CORE_PROFILER_ARGS(...) CORE_NS::PerformanceTraceEnabled<0, ##__VA_ARGS__>()
182
183 #define CORE_PROFILER_PERF_BEGIN(timerName, category, subCategory, name, color, ...) \
184 static constexpr const auto CORE_CONCAT(eventLocation, __LINE__) = \
185 CORE_NS::IPerformanceDataManager::Event { category "::" subCategory, __func__, __FILE__, __LINE__, color }; \
186 CORE_NS::CpuPerfScopeI<CORE_PROFILER_ARGS(__VA_ARGS__)> timerName( \
187 category, subCategory, name, CORE_CONCAT(eventLocation, __LINE__))
188 #define CORE_PROFILER_PERF_END(timerName) timerName.Stop()
189
190 #define CORE_PROFILER_PERF_SCOPE(category, subCategory, name, color, ...) \
191 static constexpr const auto CORE_CONCAT(eventLocation, __LINE__) = CORE_NS::IPerformanceDataManager::Event { \
192 category "::" subCategory, \
193 __func__, \
194 __FILE__, \
195 __LINE__, \
196 color, \
197 }; \
198 CORE_NS::CpuPerfScopeI<CORE_PROFILER_ARGS(__VA_ARGS__)> CORE_CONCAT(cpuPerfScope_, __LINE__)( \
199 category, subCategory, name, CORE_CONCAT(eventLocation, __LINE__))
200
201 #define CORE_PROFILER_SYMBOL(name, value) constexpr const char* name = value
202
203 #define CORE_PROFILER_APPNAME(txt, size, ...) \
204 if (auto tracer = CORE_NS::GetTracer<CORE_PROFILER_ARGS(__VA_ARGS__)>()) { \
205 tracer->AppInfo(txt, size); \
206 }
207
208 #define CORE_PROFILER_MESSAGEL(msg, ...) \
209 if (auto tracer = CORE_NS::GetTracer<CORE_PROFILER_ARGS(__VA_ARGS__)>()) { \
210 tracer->Message(msg, 0); \
211 }
212
213 #define CORE_PROFILER_MESSAGE(msg, size, ...) \
214 if (auto tracer = CORE_NS::GetTracer<CORE_PROFILER_ARGS(__VA_ARGS__)>()) { \
215 tracer->Message(msg, size); \
216 }
217
218 #define CORE_PROFILER_PLOT(name, val, ...) \
219 if (auto tracer = CORE_NS::GetTracer<CORE_PROFILER_ARGS(__VA_ARGS__)>()) { \
220 tracer->Plot(name, val); \
221 }
222
223 #define CORE_PROFILER_MARK_GLOBAL_FRAME_CHANGED(...) \
224 if (auto tracer = CORE_NS::GetTracer<CORE_PROFILER_ARGS(__VA_ARGS__)>()) { \
225 tracer->GlobalFrameChanged(); \
226 }
227
228 #define CORE_PROFILER_MARK_FRAME_START(name, ...) \
229 if (auto tracer = CORE_NS::GetTracer<CORE_PROFILER_ARGS(__VA_ARGS__)>()) { \
230 tracer->FrameBegin(name); \
231 }
232
233 #define CORE_PROFILER_MARK_FRAME_END(name, ...) \
234 if (auto tracer = CORE_NS::GetTracer<CORE_PROFILER_ARGS(__VA_ARGS__)>()) { \
235 tracer->FrameEnd(name); \
236 }
237
238 #define CORE_PROFILER_ALLOC_N(ptr, size, name, ...) \
239 if (auto tracer = CORE_NS::GetTracer<CORE_PROFILER_ARGS(__VA_ARGS__)>()) { \
240 tracer->MemAllocNamed(ptr, size, false, name); \
241 }
242
243 #define CORE_PROFILER_FREE_N(ptr, name, ...) \
244 if (auto tracer = CORE_NS::GetTracer<CORE_PROFILER_ARGS(__VA_ARGS__)>()) { \
245 tracer->MemFreeNamed(ptr, false, name); \
246 }
247
248 #define CORE_CPU_PERF_BEGIN(timerName, category, subCategory, name, color, ...) \
249 CORE_PROFILER_PERF_BEGIN( \
250 timerName, category, subCategory, name, color, CORE_NS::PROFILER_SUBSYSTEM_DEFAULT, ##__VA_ARGS__)
251 #define CORE_CPU_PERF_END(timerName) CORE_PROFILER_PERF_END(timerName)
252 #define CORE_CPU_PERF_SCOPE(category, subCategory, name, color, ...) \
253 CORE_PROFILER_PERF_SCOPE(category, subCategory, name, color, CORE_NS::PROFILER_SUBSYSTEM_DEFAULT, ##__VA_ARGS__)
254 #else
255 #define CORE_PROFILER_PERF_BEGIN(timerName, category, subCategory, name, color, ...)
256 #define CORE_PROFILER_PERF_END(timerName)
257 #define CORE_PROFILER_PERF_SCOPE(category, subCategory, name, color, ...)
258 #define CORE_PROFILER_SYMBOL(name, value)
259 #define CORE_PROFILER_APPNAME(name, ...)
260 #define CORE_PROFILER_MESSAGEL(msg, ...)
261 #define CORE_PROFILER_MESSAGE(msg, size, ...)
262 #define CORE_PROFILER_PLOT(name, val, ...)
263 #define CORE_PROFILER_MARK_GLOBAL_FRAME_CHANGED(...)
264 #define CORE_PROFILER_MARK_FRAME_START(name, ...)
265 #define CORE_PROFILER_MARK_FRAME_END(name, ...)
266 #define CORE_PROFILER_ALLOC_N(ptr, size, name, ...)
267 #define CORE_PROFILER_FREE_N(ptr, name, ...)
268 #define CORE_CPU_PERF_BEGIN(timerName, category, subCategory, name, ...)
269 #define CORE_CPU_PERF_END(timerName)
270 #define CORE_CPU_PERF_SCOPE(category, subCategory, name, ...)
271 #endif
272
273 #endif // API_CORE_PERF_CPU_PERF_SCOPE_H
274