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 #include "performance_analysis.h"
16
17 #include <climits>
18
19 #include "db_errno.h"
20 #include "log_print.h"
21 #include "macro_utils.h"
22 #include "platform_specific.h"
23 #include "time_helper.h"
24
25 namespace DistributedDB {
26 const std::string PerformanceAnalysis::STATISTICAL_DATA_FILE_NAME_HEADER = "/data/log/statistic";
27 const std::string PerformanceAnalysis::CSV_FILE_EXTENSION = ".csv";
28 const std::string PerformanceAnalysis::DEFAULT_FILE_NAME = "default00";
29 std::once_flag PerformanceAnalysis::initFlag_;
30
GetInstance(int stepNum)31 PerformanceAnalysis *PerformanceAnalysis::GetInstance(int stepNum)
32 {
33 static PerformanceAnalysis inst(stepNum);
34 std::call_once(initFlag_, std::bind(&PerformanceAnalysis::Initialization, &inst));
35 return &inst;
36 }
37
PerformanceAnalysis(uint32_t inStepNum)38 PerformanceAnalysis::PerformanceAnalysis(uint32_t inStepNum)
39 : isOpen_(false)
40 {
41 stepNum_ = inStepNum;
42 fileNumber_ = 0;
43 fileName_ = std::string(DEFAULT_FILE_NAME) + std::to_string(fileNumber_);
44 }
45
Initialization()46 void PerformanceAnalysis::Initialization()
47 {
48 counts_.resize(stepNum_);
49 timeRecordData_.timeInfo.resize(stepNum_);
50 stepTimeRecordInfo_.resize(stepNum_);
51 for (auto &stepIter : stepTimeRecordInfo_) {
52 stepIter.max = 0;
53 stepIter.min = ULLONG_MAX;
54 stepIter.average = 0;
55 }
56 for (auto iter = counts_.begin(); iter != counts_.end(); ++iter) {
57 *iter = 0;
58 }
59 }
60
~PerformanceAnalysis()61 PerformanceAnalysis::~PerformanceAnalysis() {};
62
IsStepValid(uint32_t step) const63 bool PerformanceAnalysis::IsStepValid(uint32_t step) const
64 {
65 return (stepNum_ < MAX_TIMERECORD_STEP_NUM && step < stepNum_);
66 }
67
IsOpen() const68 bool PerformanceAnalysis::IsOpen() const
69 {
70 return isOpen_;
71 }
72
OpenPerformanceAnalysis()73 void PerformanceAnalysis::OpenPerformanceAnalysis()
74 {
75 isOpen_ = true;
76 }
77
ClosePerformanceAnalysis()78 void PerformanceAnalysis::ClosePerformanceAnalysis()
79 {
80 isOpen_ = false;
81 }
82
InsertTimeRecord(const TimePair & timePair,uint32_t step)83 bool PerformanceAnalysis::InsertTimeRecord(const TimePair &timePair, uint32_t step)
84 {
85 if (!IsStepValid(step)) {
86 return false;
87 }
88 timeRecordData_.timeInfo[step] = timePair;
89 return true;
90 }
91
GetTimeRecord(uint32_t step,TimePair & timePair) const92 bool PerformanceAnalysis::GetTimeRecord(uint32_t step, TimePair &timePair) const
93 {
94 if (!IsStepValid(step)) {
95 return false;
96 }
97 timePair = timeRecordData_.timeInfo[step];
98 return true;
99 }
100
TimeRecordStart()101 void PerformanceAnalysis::TimeRecordStart()
102 {
103 if (!IsOpen()) {
104 return;
105 }
106 StepTimeRecordStart(0);
107 }
108
TimeRecordEnd()109 void PerformanceAnalysis::TimeRecordEnd()
110 {
111 if (!IsOpen()) {
112 return;
113 }
114 StepTimeRecordEnd(0);
115 }
116
StepTimeRecordStart(uint32_t step)117 void PerformanceAnalysis::StepTimeRecordStart(uint32_t step)
118 {
119 if (!IsOpen()) {
120 return;
121 }
122 if (!IsStepValid(step)) {
123 return;
124 }
125 TimePair timePair = {0, 0};
126 uint64_t curTime = 0;
127 int errCode = OS::GetCurrentSysTimeInMicrosecond(curTime);
128 if (errCode != E_OK) {
129 LOGE("[performance_analysis] GetCurrentSysTimeInMicrosecond fail");
130 } else {
131 timePair.startTime = curTime;
132 LOGD("[performance_analysis] StepTimeRecordStart step:%" PRIu32 ", curTime:%" PRIu64, step, curTime);
133 (void)InsertTimeRecord(timePair, step);
134 }
135 }
136
StepTimeRecordEnd(uint32_t step)137 void PerformanceAnalysis::StepTimeRecordEnd(uint32_t step)
138 {
139 if (!IsOpen()) {
140 return;
141 }
142 if (!IsStepValid(step)) {
143 return;
144 }
145 TimePair timePair = {0, 0};
146 bool errCode = GetTimeRecord(step, timePair);
147 if (!errCode) {
148 return;
149 }
150 (void)InsertTimeRecord({0, 0}, step);
151
152 uint64_t curTime = 0;
153 (void)OS::GetCurrentSysTimeInMicrosecond(curTime);
154 timePair.endTime = curTime;
155 LOGD("[performance_analysis] StepTimeRecordEnd step:%" PRIu32 ", curTime:%" PRIu64, step, curTime);
156
157 if ((timePair.endTime < timePair.startTime) || (timePair.startTime == 0) || (timePair.endTime == 0)) {
158 return;
159 }
160 Timestamp offset = timePair.endTime - timePair.startTime;
161 if (stepTimeRecordInfo_[step].max < offset) {
162 stepTimeRecordInfo_[step].max = offset;
163 }
164 if (offset < stepTimeRecordInfo_[step].min) {
165 stepTimeRecordInfo_[step].min = offset;
166 }
167 counts_[step]++;
168 if (counts_[step] == 0) {
169 stepTimeRecordInfo_[step].average = 0;
170 return;
171 }
172 stepTimeRecordInfo_[step].average += (static_cast<float>(offset) -
173 stepTimeRecordInfo_[step].average) / counts_[step];
174 }
175
GetStatistics()176 std::string PerformanceAnalysis::GetStatistics()
177 {
178 std::string result;
179 for (size_t i = 0; i < stepTimeRecordInfo_.size(); i++) {
180 if (stepTimeRecordInfo_[i].max != 0) {
181 result += "\nstep : " + std::to_string(i) + "\n";
182 result += "max: " + std::to_string(stepTimeRecordInfo_[i].max) + "\n";
183 result += "min: " + std::to_string(stepTimeRecordInfo_[i].min) + "\n";
184 result += "average: " +
185 std::to_string(static_cast<uint64_t>(stepTimeRecordInfo_[i].average)) + "\n";
186 result += "count: " + std::to_string(counts_[i]) + "\n";
187 }
188 }
189 OutStatistics();
190 Clear();
191 return result;
192 }
193
OutStatistics()194 void PerformanceAnalysis::OutStatistics()
195 {
196 std::string addrStatistics = STATISTICAL_DATA_FILE_NAME_HEADER + fileName_ + CSV_FILE_EXTENSION;
197 outFile.open(addrStatistics, std::ios_base::app);
198 if (!outFile.is_open()) {
199 return;
200 }
201 // This part filters the zeros data
202 outFile << "stepNum, maxTime(us), minTime(us), averageTime(us), count,\n";
203 for (size_t i = 0; i < stepTimeRecordInfo_.size(); i++) { // output to performance file
204 if (stepTimeRecordInfo_[i].max != 0) {
205 outFile << i << "," << stepTimeRecordInfo_[i].max<< "," << stepTimeRecordInfo_[i].min
206 << "," << stepTimeRecordInfo_[i].average << "," << counts_[i] << "," << "\n";
207 }
208 }
209 LOGD("outFile success and exit!");
210 outFile.close();
211 }
212
Clear()213 void PerformanceAnalysis::Clear()
214 {
215 counts_.clear();
216 timeRecordData_.timeInfo.clear();
217 stepTimeRecordInfo_.clear();
218 counts_.resize(stepNum_);
219 timeRecordData_.timeInfo.resize(stepNum_);
220 stepTimeRecordInfo_.resize(stepNum_);
221 for (auto &iter : stepTimeRecordInfo_) {
222 iter.max = 0;
223 iter.min = ULLONG_MAX;
224 iter.average = 0;
225 }
226 fileName_ = std::string(DEFAULT_FILE_NAME) + std::to_string(fileNumber_);
227 }
228
SetFileName(const std::string & fileName)229 void PerformanceAnalysis::SetFileName(const std::string &fileName)
230 {
231 fileName_ = fileName;
232 }
233 } // namespace DistributedDB
234