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