• 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 #include "ecmascript/pgo_profiler/pgo_profiler_saver.h"
17 
18 #include "ecmascript/platform/file.h"
19 
20 namespace panda::ecmascript {
21 static const std::string PROFILE_FILE_NAME = "/modules.ap";
Destroy()22 void PGOProfilerSaver::Destroy()
23 {
24     if (!isInitialized_) {
25         return;
26     }
27     PGOProfilerHeader::Destroy(&header_);
28     pandaFileInfos_.reset();
29     globalRecordInfos_->Clear();
30     globalRecordInfos_.reset();
31     isInitialized_ = false;
32 }
33 
InitializeData()34 bool PGOProfilerSaver::InitializeData()
35 {
36     if (!isInitialized_) {
37         if (!RealPath(outDir_, realOutPath_, false)) {
38             return false;
39         }
40         realOutPath_ += PROFILE_FILE_NAME;
41         LOG_ECMA(INFO) << "Save profiler to file:" << realOutPath_;
42         PGOProfilerHeader::Build(&header_, PGOProfilerHeader::LastSize());
43         pandaFileInfos_ = std::make_unique<PGOPandaFileInfos>();
44         globalRecordInfos_ = std::make_unique<PGORecordDetailInfos>(hotnessThreshold_);
45         isInitialized_ = true;
46     }
47     return true;
48 }
49 
SamplePandaFileInfo(uint32_t checksum)50 void PGOProfilerSaver::SamplePandaFileInfo(uint32_t checksum)
51 {
52     if (!isInitialized_) {
53         return;
54     }
55     pandaFileInfos_->Sample(checksum);
56 }
57 
Merge(const PGORecordDetailInfos & recordInfos)58 void PGOProfilerSaver::Merge(const PGORecordDetailInfos &recordInfos)
59 {
60     if (!isInitialized_) {
61         return;
62     }
63     os::memory::LockHolder lock(mutex_);
64     globalRecordInfos_->Merge(recordInfos);
65 }
66 
Save()67 void PGOProfilerSaver::Save()
68 {
69     if (!isInitialized_) {
70         return;
71     }
72     os::memory::LockHolder lock(mutex_);
73     SaveProfiler();
74 }
75 
SaveProfiler(const SaveTask * task)76 void PGOProfilerSaver::SaveProfiler(const SaveTask *task)
77 {
78     std::ofstream fileStream(realOutPath_.c_str());
79     if (!fileStream.is_open()) {
80         LOG_ECMA(ERROR) << "The file path(" << realOutPath_ << ") open failure!";
81         return;
82     }
83     pandaFileInfos_->ProcessToBinary(fileStream, header_->GetPandaInfoSection());
84     globalRecordInfos_->ProcessToBinary(task, fileStream, header_->GetRecordInfoSection());
85     header_->ProcessToBinary(fileStream);
86     fileStream.close();
87 }
88 
TerminateSaveTask()89 void PGOProfilerSaver::TerminateSaveTask()
90 {
91     if (!isInitialized_) {
92         return;
93     }
94     Taskpool::GetCurrentTaskpool()->TerminateTask(GLOBAL_TASK_ID, TaskType::PGO_SAVE_TASK);
95 }
96 
PostSaveTask()97 void PGOProfilerSaver::PostSaveTask()
98 {
99     if (!isInitialized_) {
100         return;
101     }
102     Taskpool::GetCurrentTaskpool()->PostTask(std::make_unique<SaveTask>(this, GLOBAL_TASK_ID));
103 }
104 
StartSaveTask(const SaveTask * task)105 void PGOProfilerSaver::StartSaveTask(const SaveTask *task)
106 {
107     if (task == nullptr) {
108         return;
109     }
110     if (task->IsTerminate()) {
111         LOG_ECMA(ERROR) << "StartSaveTask: task is already terminate";
112         return;
113     }
114     os::memory::LockHolder lock(mutex_);
115     SaveProfiler(task);
116 }
117 
LoadAPTextFile(const std::string & inPath)118 bool PGOProfilerSaver::LoadAPTextFile(const std::string &inPath)
119 {
120     if (!isInitialized_) {
121         return false;
122     }
123     std::string realPath;
124     if (!RealPath(inPath, realPath)) {
125         return false;
126     }
127 
128     std::ifstream fileStream(realPath.c_str());
129     if (!fileStream.is_open()) {
130         LOG_ECMA(ERROR) << "The file path(" << realOutPath_ << ") open failure!";
131         return false;
132     }
133 
134     if (!header_->ParseFromText(fileStream)) {
135         LOG_ECMA(ERROR) << "header format error";
136         return false;
137     }
138     if (!pandaFileInfos_->ParseFromText(fileStream)) {
139         LOG_ECMA(ERROR) << "panda file info format error";
140         return false;
141     }
142     if (!globalRecordInfos_->ParseFromText(fileStream)) {
143         LOG_ECMA(ERROR) << "record info format error";
144         return false;
145     }
146 
147     return true;
148 }
149 } // namespace panda::ecmascript
150