1 /* 2 * Copyright (c) 2020 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 OHOS_ACELITE_JS_PROFILER_H 16 #define OHOS_ACELITE_JS_PROFILER_H 17 #include <cstdint> 18 #include <stddef.h> 19 #include "acelite_config.h" 20 #include "js_config.h" 21 #include "memory_heap.h" 22 #include "non_copyable.h" 23 24 /* 25 * Wrapper macro, use directly in code after including this header file. 26 */ 27 #if IS_ENABLED(JS_PROFILER) 28 // start tracing for one given phase, and return a traceId which will be used when calling STOP_TRACING 29 #define START_TRACING(traceTag) JSProfiler::GetInstance()->PushTrace(traceTag, 0, 0) 30 // start tracing for one given phase, and provids the component name together 31 #define START_TRACING_WITH_COMPONENT_NAME(traceTag, componentNameId) \ 32 JSProfiler::GetInstance()->PushTrace(traceTag, componentNameId, 0) 33 #define START_TRACING_WITH_EXTRA_INFO(traceTag, componentNameId, extraInfoId) \ 34 JSProfiler::GetInstance()->PushTrace(traceTag, componentNameId, extraInfoId) 35 // stop tracing 36 #define STOP_TRACING() JSProfiler::GetInstance()->PopTrace() 37 #define OUTPUT_TRACE() JSProfiler::GetInstance()->Output() 38 #else // ENABLED(JS_PROFILER) 39 #define START_TRACING(traceTag) 40 #define START_TRACING_WITH_COMPONENT_NAME(traceTag, componentNameId) 41 #define START_TRACING_WITH_EXTRA_INFO(traceTag, componentNameId, extraInfoId) 42 #define STOP_TRACING() 43 #define OUTPUT_TRACE() 44 #endif // ENABLED(JS_PROFILER) 45 46 // invoked into compiling only if performance measurement enabled 47 #if IS_ENABLED(JS_PROFILER) 48 namespace OHOS { 49 namespace ACELite { 50 /** 51 * Define all trace point tags for performance measurement. 52 * 53 * NOTE: KEEP SYNC WITH g_PerformanceTagName in cpp file 54 */ 55 enum PerformanceTag { 56 P_UNKNOWN = 0X00, 57 LAUNCH, 58 ENGINE_INIT, 59 FWK_INIT, 60 JS_BEGIN, 61 JS_FWK_EVAL, // 5 62 JS_APP_INIT, // 6 63 JS_INIT_STATE, // 7 64 JS_INIT_DATA_GET_DATA, // 8 65 JS_INIT_DATA_PROXY, // 9 66 JS_INIT_DATA_OBSERVE, // 10 67 JS_END, 68 FWK_CODE_LOAD, 69 FWK_CODE_EVAL, 70 APP_CODE_LOAD, 71 APP_CODE_EVAL, 72 PAGE_CODE_LOAD, 73 PAGE_CODE_EVAL, 74 STYLESHEET_INIT, 75 APP_ON_CREATE, 76 APP_ON_DESTROY, 77 ROUTER_REPLACE, 78 PAGE_TRANSFER_DATA, 79 PAGE_ON_INIT, 80 PAGE_ON_READY, 81 PAGE_ON_SHOW, 82 PAGE_ON_BACKGROUND, 83 PAGE_ON_DESTROY, 84 RENDER, 85 ADD_TO_ROOT_VIEW, 86 RENDER_CREATE_COMPONENT, 87 RENDER_COMBINE_STYLE, 88 RENDER_BIND_JS_OBJECT, 89 RENDER_PARSE_ATTR, 90 RENDER_PARSE_EVENT, 91 RENDER_APPLY_STYLE, 92 RENDER_PROCESS_CHILDREN, 93 SET_ATTR_PARSE_EXPRESSION, 94 SET_ATTR_STRING_OF, 95 SET_ATTR_PARSE_KEY_ID, 96 SET_ATTR_SET_TO_NATIVE, 97 APPLY_STYLE_ITEM, 98 WATCHER_CALLBACK_FUNC, 99 FOR_WATCHER_CALLBACK_FUNC, 100 WATCHER_CONSTRUCT 101 }; 102 103 /** 104 * The max count of tracing we can support at the same time. 105 * NOTE: please define this value as a multiple of 2, and dont make it's bigger than 256 106 */ 107 constexpr uint8_t maxCountAllAtOnce = 16; 108 109 // need more data slots for static profiling mode, as we record them all before output the result 110 constexpr uint16_t maxTracingDataCount = 512; 111 112 /** 113 * Performance data holder. 114 */ 115 struct PerformanceData { 116 uint64_t start; // count in clock ticks (usually 1ms) 117 uint64_t end; 118 uint8_t label; // what's the phase this time cost data is representing 119 uint8_t description; // other description, NOTE: we don't do string copy, so const char* must be given 120 uint8_t component; 121 }; 122 123 #if (FEATURE_ACELITE_MC_JS_PROFILER == 1) 124 static constexpr uint8_t MSG_LENGTH = 20; 125 126 struct ProfilerMsg { 127 char msg[MSG_LENGTH] = {'\0'}; 128 }; 129 #endif 130 131 /** 132 * @brief The JSProfiler class is an runtime performance recorder and outputter, used for recording 133 * runtime timecost mainly. Implemented for development and will be disabled for release version. 134 */ 135 class JSProfiler final : public MemoryHeap { 136 public: 137 ACE_DISALLOW_COPY_AND_MOVE(JSProfiler); 138 /** 139 * @brief Default constructor. 140 */ 141 JSProfiler(); 142 143 /** 144 * @brief Default destructor. 145 */ 146 ~JSProfiler(); 147 148 /** 149 * @brief Use static global variable for easy access in different source code file. 150 * 151 * @return global JSProfiler object 152 */ 153 static JSProfiler *GetInstance(); 154 155 /** 156 * Called to free all performance data records and the global JSProfiler object. 157 */ 158 void Release(); 159 160 #if (FEATURE_ACELITE_MC_JS_PROFILER == 1) 161 /** 162 * @brief Flush output to file. 163 */ 164 static void FlushProfilerMsg(void *data); 165 #endif 166 167 /** 168 * @brief Clean all performance record in data_. 169 */ 170 void ResetData(); 171 172 /** 173 * @brief Record the current timestamp for the given tag. 174 * 175 * @param [in] tag The given phase's trace name, must be given. 176 * @param [in] name The component name of the current tracing phase, default is null. 177 * @param [in] description The extra description string id (must can be parsed by KeyParser) 178 * for this trace, default is null. 179 * 180 */ 181 void PushTrace(PerformanceTag tag, uint8_t name, uint8_t description); 182 183 /** 184 * @brief Calculate the time interval and log out. 185 * 186 */ 187 void PopTrace(); 188 189 /** 190 * @brief Calculate all time cost and output to trace. 191 * 192 * NOTE: Delay the elapsed time calculating to this method to save band width. 193 */ 194 void Output(); 195 196 /** 197 * @brief Get current timestamp for recording. 198 * 199 * @return the current timestamp, count in clock tick, will be converted into ms during output performance data 200 */ 201 uint64_t GetCurrentClockTick() const; 202 203 /** 204 * @brief Calculate the elapsed milliseconds from two input clock timestamp. 205 * 206 * @param [in] start The start timestamp, must count in clock tick. 207 * @param [in] end The end timestamp, must count in clock tick. 208 * 209 * @return the elapsed time from start to end, count in ms 210 */ 211 uint64_t CalculateElapsedTime(uint64_t start, uint64_t end) const; 212 213 /** 214 * @brief Check if the profiler is enabled or not. 215 * 216 * @return true for enabled, false for not 217 */ 218 bool IsEnabled(); 219 220 /** 221 * @brief malloc data buffer for saving performance data. 222 */ 223 void PrepareDataBuffer(); 224 225 private: 226 /** 227 * The trace id stack, MAX_COUNT_ALL_AT_ONCE at the same time 228 */ 229 uint16_t traceIdStack_[maxTracingDataCount] = {0}; 230 231 /** 232 * The tracing data 233 */ 234 PerformanceData *data_ = nullptr; 235 236 uint16_t dataCount_ = 0; 237 uint16_t traceIdSlot_ = 0; 238 bool enabled_ = false; 239 #if (FEATURE_ACELITE_MC_JS_PROFILER == 1) 240 static constexpr uint8_t PROFILER_MSG_LENGTH = 128; 241 static constexpr uint8_t TEXT_LENGTH = 30; 242 ProfilerMsg *msg_ = nullptr; 243 #endif 244 }; 245 } // namespace ACELite 246 } // namespace OHOS 247 248 #endif // ENABLED(JS_PROFILER) 249 #endif // OHOS_ACELITE_JS_PROFILER_H 250