1 /* 2 * Copyright (c) 2021-2023 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 16 #ifndef ECMASCRIPT_DFX_CPU_PROFILER_SAMPLES_RECORD_H 17 #define ECMASCRIPT_DFX_CPU_PROFILER_SAMPLES_RECORD_H 18 19 #include <atomic> 20 #include <ctime> 21 #include <cstring> 22 #include <fstream> 23 #include <semaphore.h> 24 25 #include "ecmascript/dfx/stackinfo/js_stackgetter.h" 26 #include "ecmascript/js_thread.h" 27 #include "ecmascript/jspandafile/method_literal.h" 28 #include "ecmascript/mem/c_containers.h" 29 #include "ecmascript/platform/mutex.h" 30 31 namespace panda::ecmascript { 32 const int MAX_STACK_SIZE = 128; // 128:the maximum size of the js stack 33 const int MAX_NODE_COUNT = 20000; // 20000:the maximum size of the array 34 const int MIN_TIME_DELTA = 10; // 10: the minimum value of the time delta 35 const int PROGRAM_NODE_ID = 2; // 2: the (program) node id 36 const int QUEUE_CAPACITY = 51; // the capacity of the circular queue is QUEUE_CAPACITY - 1 37 const size_t NAPI_CALL_SETP = 2; // 2: step size of the variable napiCallIdx in while loop 38 const size_t PRE_IDX_RANGE = 5; // 5: length of variable preIdx looping backward 39 const size_t SUB_LEN = 6; // 6: Truncate the path length 40 41 struct FrameInfo { 42 int scriptId = 0; 43 int lineNumber = -1; 44 int columnNumber = -1; 45 std::string functionName = ""; 46 std::string moduleName = ""; 47 std::string url = ""; 48 }; 49 50 struct CpuProfileNode { 51 int id = 0; 52 int parentId = 0; 53 int hitCount = 0; 54 struct FrameInfo codeEntry; 55 CVector<int> children; 56 }; 57 58 struct ProfileInfo { 59 uint64_t tid = 0; 60 uint64_t startTime = 0; 61 uint64_t stopTime = 0; 62 struct CpuProfileNode nodes[MAX_NODE_COUNT]; 63 int nodeCount = 0; 64 CVector<int> samples; 65 CVector<int> timeDeltas; 66 // state time statistic 67 uint64_t gcTime = 0; 68 uint64_t cInterpreterTime = 0; 69 uint64_t asmInterpreterTime = 0; 70 uint64_t aotTime = 0; 71 uint64_t asmInterpreterDeoptTime = 0; 72 uint64_t builtinTime = 0; 73 uint64_t napiTime = 0; 74 uint64_t arkuiEngineTime = 0; 75 uint64_t runtimeTime = 0; 76 uint64_t jitTime = 0; 77 uint64_t otherTime = 0; 78 }; 79 80 struct FrameStackAndInfo { 81 struct FrameInfoTemp frameInfoTemps[MAX_STACK_SIZE] = {}; 82 struct MethodKey frameStack[MAX_STACK_SIZE] = {}; 83 int frameInfoTempsLength {}; 84 int frameStackLength {}; 85 uint64_t timeStamp {}; 86 }; 87 88 class SamplesQueue { 89 public: 90 SamplesQueue() = default; 91 ~SamplesQueue() = default; 92 93 NO_COPY_SEMANTIC(SamplesQueue); 94 NO_MOVE_SEMANTIC(SamplesQueue); 95 96 void PostFrame(FrameInfoTemp *frameInfoTemps, MethodKey *frameStack, 97 int frameInfoTempsLength, int frameStackLength); 98 void PostNapiFrame(CVector<FrameInfoTemp> &napiFrameInfoTemps, 99 CVector<MethodKey> &napiFrameStack); 100 FrameStackAndInfo *PopFrame(); 101 bool IsEmpty(); 102 bool IsFull(); 103 int GetSize(); 104 int GetFrontIndex(); 105 int GetRearIndex(); 106 bool CheckAndCopy(char *dest, size_t length, const char *src) const; 107 108 private: 109 FrameStackAndInfo frames_[QUEUE_CAPACITY] = {}; 110 int front_ = 0; 111 int rear_ = 0; 112 Mutex mtx_; 113 }; 114 115 class SamplesRecord { 116 public: 117 SamplesRecord(); 118 virtual ~SamplesRecord(); 119 120 void NodeInit(); 121 void AddSample(FrameStackAndInfo *frame); 122 void AddEmptyStackSample(uint64_t sampleTimeStamp); 123 void StringifySampleData(); 124 int GetMethodNodeCount() const; 125 int GetframeStackLength() const; 126 std::string GetSampleData() const; 127 std::string GetModuleName(char *recordName); 128 void SetThreadStartTime(uint64_t threadStartTime); 129 uint64_t GetThreadStartTime(); 130 void SetThreadStopTime(); 131 void SetFileName(std::string &fileName); 132 const std::string GetFileName() const; 133 std::unique_ptr<struct ProfileInfo> GetProfileInfo(); 134 bool GetIsStart() const; 135 void SetIsStart(bool isStart); 136 bool GetGcState() const; 137 void SetGcState(bool gcState); 138 bool GetRuntimeState() const; 139 void SetRuntimeState(bool runtimeState); 140 int SemInit(int index, int pshared, int value); 141 int SemPost(int index); 142 int SemWait(int index); 143 int SemDestroy(int index); 144 const CMap<struct MethodKey, struct FrameInfo> &GetStackInfo() const; 145 void InsertStackInfo(struct MethodKey &methodKey, struct FrameInfo &codeEntry); 146 bool PushFrameStack(struct MethodKey &methodKey); 147 bool PushStackInfo(const FrameInfoTemp &frameInfoTemp); 148 bool GetCallNapiFlag(); 149 void SetCallNapiFlag(bool flag); 150 bool PushNapiFrameStack(struct MethodKey &methodKey); 151 bool PushNapiStackInfo(const FrameInfoTemp &frameInfoTemp); 152 int GetNapiFrameStackLength(); 153 void ClearNapiStack(); 154 void PostFrame(); 155 void PostNapiFrame(); 156 void ResetFrameLength(); 157 uint64_t GetCallTimeStamp(); 158 void SetCallTimeStamp(uint64_t timeStamp); 159 void AddTraceEvent(bool isFinish); 160 void AddStartTraceEvent(); 161 SetEnableVMTag(bool flag)162 void SetEnableVMTag(bool flag) 163 { 164 enableVMTag_ = flag; 165 } 166 SetSourceMapTranslateCallback(SourceMapTranslateCallback cb)167 void SetSourceMapTranslateCallback(SourceMapTranslateCallback cb) 168 { 169 sourceMapTranslateCallback_ = cb; 170 } 171 SetTimeDeltaThreshold(uint32_t timeDeltaThreshold)172 void SetTimeDeltaThreshold(uint32_t timeDeltaThreshold) 173 { 174 timeDeltaThreshold_ = timeDeltaThreshold; 175 } 176 177 std::ofstream fileHandle_; 178 SamplesQueue *samplesQueue_ {nullptr}; 179 180 private: 181 void StringifyStateTimeStatistic(); 182 void StringifyNodes(); 183 void StringifySamples(); 184 struct FrameInfo GetMethodInfo(struct MethodKey &methodKey); 185 std::string AddRunningState(char *functionName, RunningState state, kungfu::DeoptType type); 186 void FrameInfoTempToMap(FrameInfoTemp *frameInfoTemps, int frameInfoTempLength); 187 void NapiFrameInfoTempToMap(); 188 void StatisticStateTime(int timeDelta, RunningState state); 189 void TranslateUrlPositionBySourceMap(struct FrameInfo &codeEntry); 190 191 int previousId_ = 0; 192 RunningState previousState_ = RunningState::OTHER; 193 uint64_t previousTimeStamp_ = 0; 194 std::atomic_bool gcState_ = false; 195 std::atomic_bool runtimeState_ = false; 196 std::atomic_bool isStart_ = false; 197 std::atomic_bool callNapi_ = false; 198 std::unique_ptr<struct ProfileInfo> profileInfo_; 199 CMap<struct NodeKey, int> nodeMap_; 200 std::string sampleData_ = ""; 201 std::string fileName_ = ""; 202 sem_t sem_[3]; // 3 : sem_ size is three. 203 CMap<struct MethodKey, struct FrameInfo> stackInfoMap_; 204 struct MethodKey frameStack_[MAX_STACK_SIZE] = {}; 205 int frameStackLength_ = 0; 206 CMap<std::string, int> scriptIdMap_; 207 FrameInfoTemp frameInfoTemps_[MAX_STACK_SIZE] = {}; 208 int frameInfoTempLength_ = 0; 209 // napi stack 210 CVector<struct MethodKey> napiFrameStack_; 211 CVector<FrameInfoTemp> napiFrameInfoTemps_; 212 bool enableVMTag_ {false}; 213 uint64_t callTimeStamp_ = 0; 214 uint32_t timeDeltaThreshold_ = 0; 215 SourceMapTranslateCallback sourceMapTranslateCallback_ {nullptr}; 216 int traceEventNodePos_ = 0; 217 uint32_t traceEventSamplePos_ = 0; 218 219 friend class SamplesRecordFriendTest; 220 }; 221 } // namespace panda::ecmascript 222 #endif // ECMASCRIPT_DFX_CPU_PROFILER_SAMPLES_RECORD_H 223