1 /* 2 * Copyright (c) 2021 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_TOOLING_AGENT_HEAPPROFILER_IMPL_H 17 #define ECMASCRIPT_TOOLING_AGENT_HEAPPROFILER_IMPL_H 18 19 #include <uv.h> 20 21 #include "base/pt_params.h" 22 #include "base/pt_events.h" 23 #include "base/pt_returns.h" 24 #include "dispatcher.h" 25 #include "protocol_handler.h" 26 #include "protocol_channel.h" 27 28 #include "ecmascript/dfx/hprof/progress.h" 29 #include "ecmascript/dfx/hprof/stream.h" 30 #include "ecmascript/napi/include/dfx_jsnapi.h" 31 #include "libpandabase/macros.h" 32 33 #include <sys/time.h> 34 35 static const double INTERVAL = 0.2; 36 namespace panda::ecmascript::tooling { 37 class HeapProfilerImpl final { 38 public: HeapProfilerImpl(const EcmaVM * vm,ProtocolChannel * channel)39 explicit HeapProfilerImpl(const EcmaVM *vm, ProtocolChannel *channel) 40 : vm_(vm), frontend_(channel), stream_(&frontend_) {} 41 ~HeapProfilerImpl() = default; 42 43 DispatchResponse AddInspectedHeapObject(const AddInspectedHeapObjectParams ¶ms); 44 DispatchResponse CollectGarbage(); 45 DispatchResponse Enable(); 46 DispatchResponse Disable(); 47 DispatchResponse GetHeapObjectId(const GetHeapObjectIdParams ¶ms, HeapSnapshotObjectId *objectId); 48 DispatchResponse GetObjectByHeapObjectId(const GetObjectByHeapObjectIdParams ¶ms, 49 std::unique_ptr<RemoteObject> *remoteObjectResult); 50 DispatchResponse GetSamplingProfile(std::unique_ptr<SamplingHeapProfile> *profile); 51 DispatchResponse StartSampling(const StartSamplingParams ¶ms); 52 DispatchResponse StartTrackingHeapObjects(const StartTrackingHeapObjectsParams ¶ms); 53 static void HeapTrackingCallback(uv_timer_t* handle); 54 DispatchResponse StopSampling(std::unique_ptr<SamplingHeapProfile> *profile); 55 DispatchResponse StopTrackingHeapObjects(const StopTrackingHeapObjectsParams ¶ms); 56 // The params type of TakeHeapSnapshot is the same as of StopTrackingHeapObjects. 57 DispatchResponse TakeHeapSnapshot(const StopTrackingHeapObjectsParams ¶ms); 58 59 class DispatcherImpl final : public DispatcherBase { 60 public: DispatcherImpl(ProtocolChannel * channel,std::unique_ptr<HeapProfilerImpl> heapprofiler)61 DispatcherImpl(ProtocolChannel *channel, std::unique_ptr<HeapProfilerImpl> heapprofiler) 62 : DispatcherBase(channel), heapprofiler_(std::move(heapprofiler)) {} 63 ~DispatcherImpl() override = default; 64 65 void Dispatch(const DispatchRequest &request) override; 66 void AddInspectedHeapObject(const DispatchRequest &request); 67 void CollectGarbage(const DispatchRequest &request); 68 void Enable(const DispatchRequest &request); 69 void Disable(const DispatchRequest &request); 70 void GetHeapObjectId(const DispatchRequest &request); 71 void GetObjectByHeapObjectId(const DispatchRequest &request); 72 void GetSamplingProfile(const DispatchRequest &request); 73 void StartSampling(const DispatchRequest &request); 74 void StartTrackingHeapObjects(const DispatchRequest &request); 75 void StopSampling(const DispatchRequest &request); 76 void StopTrackingHeapObjects(const DispatchRequest &request); 77 void TakeHeapSnapshot(const DispatchRequest &request); 78 79 private: 80 NO_COPY_SEMANTIC(DispatcherImpl); 81 NO_MOVE_SEMANTIC(DispatcherImpl); 82 83 using AgentHandler = void (HeapProfilerImpl::DispatcherImpl::*)(const DispatchRequest &request); 84 std::unique_ptr<HeapProfilerImpl> heapprofiler_ {}; 85 }; 86 87 private: 88 NO_COPY_SEMANTIC(HeapProfilerImpl); 89 NO_MOVE_SEMANTIC(HeapProfilerImpl); 90 91 class Frontend { 92 public: Frontend(ProtocolChannel * channel)93 explicit Frontend(ProtocolChannel *channel) : channel_(channel) {} 94 ~Frontend() = default; 95 96 void AddHeapSnapshotChunk(char *data, int32_t size); 97 void ReportHeapSnapshotProgress(int32_t done, int32_t total); 98 void HeapStatsUpdate(HeapStat* updateData, int32_t count); 99 void LastSeenObjectId(int32_t lastSeenObjectId, int64_t timeStampUs); 100 void ResetProfiles(); 101 102 private: 103 bool AllowNotify() const; 104 105 ProtocolChannel *channel_ {nullptr}; 106 }; 107 108 class HeapProfilerStream final : public Stream { 109 public: HeapProfilerStream(Frontend * frontend)110 explicit HeapProfilerStream(Frontend *frontend) 111 : frontend_(frontend) {} 112 EndOfStream()113 void EndOfStream() override {} GetSize()114 int GetSize() override 115 { 116 static const int heapProfilerChunkSise = 100_KB; 117 return heapProfilerChunkSise; 118 } WriteChunk(char * data,int32_t size)119 bool WriteChunk(char *data, int32_t size) override 120 { 121 if (!Good()) { 122 return false; 123 } 124 frontend_->AddHeapSnapshotChunk(data, size); 125 return true; 126 } Good()127 bool Good() override 128 { 129 return frontend_ != nullptr; 130 } 131 UpdateHeapStats(HeapStat * updateData,int32_t count)132 void UpdateHeapStats(HeapStat* updateData, int32_t count) override 133 { 134 if (!Good()) { 135 return; 136 } 137 frontend_->HeapStatsUpdate(updateData, count); 138 } 139 UpdateLastSeenObjectId(int32_t lastSeenObjectId,int64_t timeStampUs)140 void UpdateLastSeenObjectId(int32_t lastSeenObjectId, int64_t timeStampUs) override 141 { 142 if (!Good()) { 143 return; 144 } 145 frontend_->LastSeenObjectId(lastSeenObjectId, timeStampUs); 146 } 147 148 private: 149 NO_COPY_SEMANTIC(HeapProfilerStream); 150 NO_MOVE_SEMANTIC(HeapProfilerStream); 151 152 Frontend *frontend_ {nullptr}; 153 }; 154 155 class HeapProfilerProgress final : public Progress { 156 public: HeapProfilerProgress(Frontend * frontend)157 explicit HeapProfilerProgress(Frontend *frontend) 158 : frontend_(frontend) {} 159 ReportProgress(int32_t done,int32_t total)160 void ReportProgress(int32_t done, int32_t total) override 161 { 162 frontend_->ReportHeapSnapshotProgress(done, total); 163 } 164 165 private: 166 NO_COPY_SEMANTIC(HeapProfilerProgress); 167 NO_MOVE_SEMANTIC(HeapProfilerProgress); 168 169 Frontend *frontend_ {nullptr}; 170 }; 171 172 const EcmaVM *vm_ {nullptr}; 173 Frontend frontend_; 174 HeapProfilerStream stream_; 175 uv_timer_t handle_ {}; 176 }; 177 } // namespace panda::ecmascript::tooling 178 #endif