• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 const std::string JS_PATH = "entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/";
41 
42 struct FrameInfo {
43     int scriptId = 0;
44     int lineNumber = -1;
45     int columnNumber = -1;
46     std::string functionName = "";
47     std::string moduleName = "";
48     std::string url = "";
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 builtinTime = 0;
73     uint64_t napiTime = 0;
74     uint64_t arkuiEngineTime = 0;
75     uint64_t runtimeTime = 0;
76     uint64_t otherTime = 0;
77 };
78 
79 struct FrameStackAndInfo {
80     struct FrameInfoTemp frameInfoTemps[MAX_STACK_SIZE] = {};
81     struct MethodKey frameStack[MAX_STACK_SIZE] = {};
82     int frameInfoTempsLength {};
83     int frameStackLength {};
84     uint64_t timeStamp {};
85 };
86 
87 class SamplesQueue {
88 public:
89     SamplesQueue() = default;
90     ~SamplesQueue() = default;
91 
92     NO_COPY_SEMANTIC(SamplesQueue);
93     NO_MOVE_SEMANTIC(SamplesQueue);
94 
95     void PostFrame(FrameInfoTemp *frameInfoTemps, MethodKey *frameStack,
96                    int frameInfoTempsLength, int frameStackLength);
97     void PostNapiFrame(CVector<FrameInfoTemp> &napiFrameInfoTemps,
98                        CVector<MethodKey> &napiFrameStack);
99     FrameStackAndInfo *PopFrame();
100     bool IsEmpty();
101     bool IsFull();
102     int GetSize();
103     int GetFrontIndex();
104     int GetRearIndex();
105     bool CheckAndCopy(char *dest, size_t length, const char *src) const;
106 
107 private:
108     FrameStackAndInfo frames_[QUEUE_CAPACITY] = {};
109     int front_ = 0;
110     int rear_ = 0;
111     Mutex mtx_;
112 };
113 
114 class SamplesRecord {
115 public:
116     SamplesRecord();
117     virtual ~SamplesRecord();
118 
119     void NodeInit();
120     void AddSample(FrameStackAndInfo *frame);
121     void AddEmptyStackSample(uint64_t sampleTimeStamp);
122     void StringifySampleData();
123     int GetMethodNodeCount() const;
124     int GetframeStackLength() const;
125     std::string GetSampleData() const;
126     std::string GetModuleName(char *recordName);
127     void SetThreadStartTime(uint64_t threadStartTime);
128     void SetThreadStopTime();
129     void SetStartsampleData(std::string sampleData);
130     void SetFileName(std::string &fileName);
131     const std::string GetFileName() const;
132     void ClearSampleData();
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 GetBeforeGetCallNapiStackFlag();
149     void SetBeforeGetCallNapiStackFlag(bool flag);
150     bool GetAfterGetCallNapiStackFlag();
151     void SetAfterGetCallNapiStackFlag(bool flag);
152     bool GetCallNapiFlag();
153     void SetCallNapiFlag(bool flag);
154     bool PushNapiFrameStack(struct MethodKey &methodKey);
155     bool PushNapiStackInfo(const FrameInfoTemp &frameInfoTemp);
156     int GetNapiFrameStackLength();
157     void ClearNapiStack();
158     void ClearNapiCall();
159     void RecordCallNapiTime(uint64_t currentTime);
160     void RecordCallNapiAddr(const std::string &methodAddrName);
161     void FinetuneSampleData();
162     void FindSampleAndFinetune(size_t findIdx, size_t napiCallIdx, size_t &sampleIdx,
163                                uint64_t startSampleTime, uint64_t &sampleTime);
164     void FinetuneTimeDeltas(size_t idx, uint64_t napiTime, uint64_t &sampleTime, bool isEndSample);
165     void PostFrame();
166     void PostNapiFrame();
167     void ResetFrameLength();
168     uint64_t GetCallTimeStamp();
169     void SetCallTimeStamp(uint64_t timeStamp);
170     void AddTraceEvent(bool isFinish);
171     void AddStartTraceEvent();
172     std::ofstream fileHandle_;
173     SamplesQueue *samplesQueue_ {nullptr};
174 
SetEnableVMTag(bool flag)175     void SetEnableVMTag(bool flag)
176     {
177         enableVMTag_ = flag;
178     }
179 
SetSourceMapTranslateCallback(SourceMapTranslateCallback cb)180     void SetSourceMapTranslateCallback(SourceMapTranslateCallback cb)
181     {
182         sourceMapTranslateCallback_ = cb;
183     }
184 
SetTimeDeltaThreshold(uint32_t timeDeltaThreshold)185     void SetTimeDeltaThreshold(uint32_t timeDeltaThreshold)
186     {
187         timeDeltaThreshold_ = timeDeltaThreshold;
188     }
189 
190 private:
191     void StringifyStateTimeStatistic();
192     void StringifyNodes();
193     void StringifySamples();
194     struct FrameInfo GetMethodInfo(struct MethodKey &methodKey);
195     std::string AddRunningState(char *functionName, RunningState state, kungfu::DeoptType type);
196     void FrameInfoTempToMap(FrameInfoTemp *frameInfoTemps, int frameInfoTempLength);
197     void NapiFrameInfoTempToMap();
198     void StatisticStateTime(int timeDelta, RunningState state);
199     void TranslateUrlPositionBySourceMap(struct FrameInfo &codeEntry);
200 
201     int previousId_ = 0;
202     RunningState previousState_ = RunningState::OTHER;
203     uint64_t previousTimeStamp_ = 0;
204     std::atomic_bool gcState_ = false;
205     std::atomic_bool runtimeState_ = false;
206     std::atomic_bool isStart_ = false;
207     std::atomic_bool beforeCallNapi_ = false;
208     std::atomic_bool afterCallNapi_ = false;
209     std::atomic_bool callNapi_ = false;
210     std::unique_ptr<struct ProfileInfo> profileInfo_;
211     CMap<struct NodeKey, int> nodeMap_;
212     std::string sampleData_ = "";
213     std::string fileName_ = "";
214     sem_t sem_[3]; // 3 : sem_ size is three.
215     CMap<struct MethodKey, struct FrameInfo> stackInfoMap_;
216     struct MethodKey frameStack_[MAX_STACK_SIZE] = {};
217     int frameStackLength_ = 0;
218     CMap<std::string, int> scriptIdMap_;
219     FrameInfoTemp frameInfoTemps_[MAX_STACK_SIZE] = {};
220     int frameInfoTempLength_ = 0;
221     // napi stack
222     CVector<struct MethodKey> napiFrameStack_;
223     CVector<FrameInfoTemp> napiFrameInfoTemps_;
224     CVector<uint64_t> napiCallTimeVec_;
225     CVector<std::string> napiCallAddrVec_;
226     bool enableVMTag_ {false};
227     uint64_t callTimeStamp_ = 0;
228     uint32_t timeDeltaThreshold_ = 0;
229     SourceMapTranslateCallback sourceMapTranslateCallback_ {nullptr};
230     int traceEventNodePos_ = 0;
231     uint32_t traceEventSamplePos_ = 0;
232 };
233 } // namespace panda::ecmascript
234 #endif // ECMASCRIPT_DFX_CPU_PROFILER_SAMPLES_RECORD_H