• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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_PGO_PROFILER_MANAGER_H
17 #define ECMASCRIPT_PGO_PROFILER_MANAGER_H
18 
19 #include <atomic>
20 #include <csignal>
21 #include <memory>
22 
23 #include "ecmascript/pgo_profiler/pgo_profiler.h"
24 #include "ecmascript/pgo_profiler/pgo_profiler_decoder.h"
25 #include "ecmascript/pgo_profiler/pgo_profiler_encoder.h"
26 #include "os/mutex.h"
27 
28 namespace panda::ecmascript::pgo {
29 class PGOProfilerManager {
30 public:
31     using ApGenMode = PGOProfilerEncoder::ApGenMode;
32     static PGOProfilerManager *GetInstance();
33 
34     static void SavingSignalHandler(int signo);
35 
36     PGOProfilerManager() = default;
37     ~PGOProfilerManager() = default;
38 
39     NO_COPY_SEMANTIC(PGOProfilerManager);
40     NO_MOVE_SEMANTIC(PGOProfilerManager);
41 
Initialize(const std::string & outDir,uint32_t hotnessThreshold)42     void Initialize(const std::string &outDir, uint32_t hotnessThreshold)
43     {
44         // For FA jsvm, merge with existed output file
45         encoder_ = std::make_unique<PGOProfilerEncoder>(outDir, hotnessThreshold, ApGenMode::MERGE);
46     }
47 
SetBundleName(const std::string & bundleName)48     void SetBundleName(const std::string &bundleName)
49     {
50         if (encoder_) {
51             encoder_->SetBundleName(bundleName);
52         }
53     }
54 
GetBundleName()55     const std::string GetBundleName()
56     {
57         if (encoder_) {
58             return encoder_->GetBundleName();
59         }
60         return "";
61     }
62 
SetRequestAotCallback(const RequestAotCallback & cb)63     void SetRequestAotCallback(const RequestAotCallback &cb)
64     {
65         os::memory::LockHolder lock(*mutex_);
66         if (requestAotCallback_ != nullptr) {
67             return;
68         }
69         requestAotCallback_ = cb;
70     }
71 
RequestAot(const std::string & bundleName,const std::string & moduleName,RequestAotMode triggerMode)72     bool RequestAot(const std::string &bundleName, const std::string &moduleName, RequestAotMode triggerMode)
73     {
74         RequestAotCallback cb;
75         {
76             os::memory::LockHolder lock(*mutex_);
77             if (requestAotCallback_ == nullptr) {
78                 LOG_ECMA(ERROR) << "Trigger aot failed. callback is null.";
79                 return false;
80             }
81             cb = requestAotCallback_;
82         }
83         return (cb(bundleName, moduleName, static_cast<int32_t>(triggerMode)) == 0);
84     }
85 
Destroy()86     void Destroy()
87     {
88         if (encoder_) {
89             encoder_->Save();
90             encoder_->Destroy();
91             encoder_.reset();
92         }
93     }
94 
95     // Factory
Build(EcmaVM * vm,bool isEnable)96     std::shared_ptr<PGOProfiler> Build(EcmaVM *vm, bool isEnable)
97     {
98         if (isEnable) {
99             isEnable = InitializeData();
100         }
101         auto profiler = std::make_shared<PGOProfiler>(vm, isEnable);
102         {
103             os::memory::LockHolder lock(*mutex_);
104             profilers_.insert(profiler);
105         }
106         return profiler;
107     }
108 
IsEnable()109     bool IsEnable() const
110     {
111         return encoder_ && encoder_->IsInitialized();
112     }
113 
Destroy(std::shared_ptr<PGOProfiler> & profiler)114     void Destroy(std::shared_ptr<PGOProfiler> &profiler)
115     {
116         if (profiler != nullptr) {
117             profiler->HandlePGOPreDump();
118             profiler->WaitPGODumpFinish();
119             Merge(profiler.get());
120             {
121                 os::memory::LockHolder lock(*mutex_);
122                 profilers_.erase(profiler);
123             }
124             profiler.reset();
125         }
126     }
127 
Reset(const std::shared_ptr<PGOProfiler> & profiler,bool isEnable)128     void Reset(const std::shared_ptr<PGOProfiler>& profiler, bool isEnable)
129     {
130         if (isEnable) {
131             isEnable = InitializeData();
132         }
133         if (profiler) {
134             profiler->Reset(isEnable);
135         }
136     }
137 
SamplePandaFileInfo(uint32_t checksum,const CString & abcName)138     void SamplePandaFileInfo(uint32_t checksum, const CString &abcName)
139     {
140         if (encoder_) {
141             encoder_->SamplePandaFileInfo(checksum, abcName);
142         }
143     }
144 
SetModuleName(const std::string & moduleName)145     void SetModuleName(const std::string &moduleName)
146     {
147         if (encoder_) {
148             encoder_->PostResetOutPathTask(moduleName);
149         }
150     }
151 
GetPandaFileId(const CString & abcName,ApEntityId & entryId)152     bool GetPandaFileId(const CString &abcName, ApEntityId &entryId) const
153     {
154         if (encoder_) {
155             return encoder_->GetPandaFileId(abcName, entryId);
156         }
157         return false;
158     }
159 
GetPandaFileDesc(ApEntityId abcId,CString & desc)160     bool GetPandaFileDesc(ApEntityId abcId, CString &desc) const
161     {
162         if (encoder_) {
163             return encoder_->GetPandaFileDesc(abcId, desc);
164         }
165         return false;
166     }
167 
SetApGenMode(ApGenMode mode)168     void SetApGenMode(ApGenMode mode)
169     {
170         if (encoder_) {
171             encoder_->SetApGenMode(mode);
172         }
173     }
174 
Merge(PGOProfiler * profiler)175     void Merge(PGOProfiler *profiler)
176     {
177         if (encoder_ && profiler->isEnable_) {
178             encoder_->TerminateSaveTask();
179             encoder_->Merge(*profiler->recordInfos_);
180         }
181     }
182 
183     void RegisterSavingSignal();
184 
AsynSave()185     void AsynSave()
186     {
187         if (encoder_) {
188             encoder_->PostSaveTask();
189         }
190     }
191 
IsDisableAot()192     bool IsDisableAot() const
193     {
194         return disableAot_;
195     }
196 
SetDisableAot(bool state)197     void SetDisableAot(bool state)
198     {
199         disableAot_ = state;
200     }
201 
ForceSave()202     void ForceSave()
203     {
204         os::memory::LockHolder lock(*mutex_);
205         for (const auto &profiler : profilers_) {
206             profiler->DumpByForce();
207         }
208         GetInstance()->AsynSave();
209     }
210 
TextToBinary(const std::string & inPath,const std::string & outPath,uint32_t hotnessThreshold,ApGenMode mode)211     bool PUBLIC_API TextToBinary(const std::string &inPath, const std::string &outPath, uint32_t hotnessThreshold,
212                                  ApGenMode mode)
213     {
214         PGOProfilerEncoder encoder(outPath, hotnessThreshold, mode);
215         PGOProfilerEncoder decoder(outPath, hotnessThreshold, mode);
216         if (!encoder.InitializeData()) {
217             LOG_ECMA(ERROR) << "PGO Profiler encoder initialized failed";
218             return false;
219         }
220         if (!decoder.InitializeData()) {
221             LOG_ECMA(ERROR) << "PGO Profiler decoder initialized failed";
222             return false;
223         }
224         bool ret = decoder.LoadAPTextFile(inPath);
225         if (ret) {
226             encoder.Merge(decoder);
227             ret = encoder.Save();
228         }
229         encoder.Destroy();
230         decoder.Destroy();
231         return ret;
232     }
233 
BinaryToText(const std::string & inPath,const std::string & outPath,uint32_t hotnessThreshold)234     bool PUBLIC_API BinaryToText(const std::string &inPath, const std::string &outPath, uint32_t hotnessThreshold)
235     {
236         PGOProfilerDecoder decoder(inPath, hotnessThreshold);
237         if (!decoder.LoadFull()) {
238             return false;
239         }
240         bool ret = decoder.SaveAPTextFile(outPath);
241         decoder.Clear();
242         return ret;
243     }
244 
245     static bool MergeApFiles(const std::string &inFiles, const std::string &outPath, uint32_t hotnessThreshold,
246                              ApGenMode mode);
247     static bool MergeApFiles(uint32_t checksum, PGOProfilerDecoder &merger);
248 
249 private:
InitializeData()250     bool InitializeData()
251     {
252         if (!encoder_) {
253             return false;
254         }
255         bool initializedResult = encoder_->InitializeData();
256         if (initializedResult && !enableSignalSaving_) {
257             RegisterSavingSignal();
258         }
259         return initializedResult;
260     }
261 
262     bool disableAot_ {false};
263     std::unique_ptr<PGOProfilerEncoder> encoder_;
264     RequestAotCallback requestAotCallback_;
265     std::atomic_bool enableSignalSaving_ { false };
266     os::memory::Mutex *mutex_ = new os::memory::Mutex();
267     std::set<std::shared_ptr<PGOProfiler>> profilers_;
268 };
269 } // namespace panda::ecmascript::pgo
270 #endif  // ECMASCRIPT_PGO_PROFILER_MANAGER_H
271