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