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 #include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
17 #include <fstream>
18
19 #include "ecmascript/platform/file.h"
20 namespace panda::ecmascript::pgo {
21 namespace {
22 constexpr int32_t PGO_SAVING_SIGNAL = 50;
23 } // namespace
24
GetInstance()25 PGOProfilerManager* PGOProfilerManager::GetInstance()
26 {
27 static PGOProfilerManager* instance = new PGOProfilerManager();
28 return instance;
29 }
30
MergeApFiles(const std::string &inFiles, const std::string &outPath, uint32_t hotnessThreshold, ApGenMode mode)31 bool PGOProfilerManager::MergeApFiles(const std::string &inFiles, const std::string &outPath, uint32_t hotnessThreshold,
32 ApGenMode mode)
33 {
34 arg_list_t apFileNames = base::StringHelper::SplitString(inFiles, GetFileDelimiter());
35 PGOProfilerEncoder merger(outPath, hotnessThreshold, mode);
36 if (!merger.InitializeData()) {
37 LOG_ECMA(ERROR) << "PGO Profiler encoder initialized failed. outPath: " << outPath
38 << " ,hotnessThreshold: " << hotnessThreshold;
39 return false;
40 }
41 bool hasMerged = false;
42 std::string firstApFileName;
43 for (const auto &fileName : apFileNames) {
44 if (!base::StringHelper::EndsWith(fileName, ".ap")) {
45 LOG_ECMA(ERROR) << "The file path (" << fileName << ") does not end with .ap";
46 continue;
47 }
48 PGOProfilerDecoder decoder(fileName, hotnessThreshold);
49 if (!decoder.LoadFull(merger.GetAbcFilePool())) {
50 LOG_ECMA(ERROR) << "Fail to load file path (" << fileName << "), skip it.";
51 continue;
52 }
53 if (!hasMerged) {
54 firstApFileName = fileName;
55 } else {
56 if (!merger.VerifyPandaFileMatched(decoder.GetPandaFileInfos(), firstApFileName, fileName)) {
57 continue;
58 }
59 }
60 if (!decoder.IsCompatibleWithAOTFile()) {
61 LOG_ECMA(ERROR) << "The ap file (" << fileName << ") is not compatible with AOT version. skip it";
62 continue;
63 }
64 merger.Merge(decoder.GetRecordDetailInfos());
65 merger.Merge(decoder.GetPandaFileInfos());
66 hasMerged = true;
67 }
68 if (!hasMerged) {
69 LOG_ECMA(ERROR)
70 << "No ap file pass verify, no ap file compatible an version, no ap file processed. Input files: "
71 << inFiles;
72 GetInstance()->SetIsApFileCompatible(false);
73 return false;
74 }
75 GetInstance()->SetIsApFileCompatible(true);
76 merger.Save();
77 return true;
78 }
79
MergeApFiles(uint32_t checksum, PGOProfilerDecoder &merger)80 bool PGOProfilerManager::MergeApFiles(uint32_t checksum, PGOProfilerDecoder &merger)
81 {
82 uint32_t hotnessThreshold = merger.GetHotnessThreshold();
83 std::string inFiles(merger.GetInPath());
84 arg_list_t pandaFileNames = base::StringHelper::SplitString(inFiles, GetFileDelimiter());
85 if (pandaFileNames.empty()) {
86 return true;
87 }
88 merger.InitMergeData();
89 bool hasMerged = false;
90 std::string firstApFileName;
91 for (const auto &fileName : pandaFileNames) {
92 PGOProfilerDecoder decoder(fileName, hotnessThreshold);
93 if (!decoder.LoadAndVerify(checksum, merger.GetAbcFilePool())) {
94 LOG_ECMA(ERROR) << "Load and verify file (" << fileName << ") failed, skip it.";
95 continue;
96 }
97 if (!hasMerged) {
98 firstApFileName = fileName;
99 } else {
100 if (!merger.GetPandaFileInfos().VerifyChecksum(decoder.GetPandaFileInfos(), firstApFileName, fileName)) {
101 continue;
102 }
103 }
104 if (!decoder.IsCompatibleWithAOTFile()) {
105 LOG_ECMA(ERROR) << "The ap file (" << fileName << ") is not compatible with AOT version. skip it";
106 continue;
107 }
108 merger.Merge(decoder);
109 hasMerged = true;
110 }
111 if (!hasMerged) {
112 LOG_ECMA(ERROR)
113 << "No ap file pass verify, no ap file compatible an version, no ap file processed. Input files: "
114 << inFiles;
115 GetInstance()->SetIsApFileCompatible(false);
116 return false;
117 }
118 GetInstance()->SetIsApFileCompatible(true);
119 return true;
120 }
121
RegisterSavingSignal()122 void PGOProfilerManager::RegisterSavingSignal()
123 {
124 LOG_ECMA(INFO) << "Register Pgo Saving Signal";
125 if (encoder_ == nullptr) {
126 LOG_ECMA(ERROR) << "Can not register pgo saving signal, because encoder is null.";
127 return;
128 }
129 if (!encoder_->IsInitialized()) {
130 LOG_ECMA(DEBUG) << "Can not register pgo saving signal, because encoder is initialized.";
131 return;
132 }
133 signal(PGO_SAVING_SIGNAL, SavingSignalHandler);
134 enableSignalSaving_ = true;
135 }
136
SavingSignalHandler(int signo)137 void PGOProfilerManager::SavingSignalHandler(int signo)
138 {
139 if (signo != PGO_SAVING_SIGNAL) {
140 return;
141 }
142
143 PGOProfilerManager::GetInstance()->ForceSave();
144 }
145 } // namespace panda::ecmascript::pgo
146