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