• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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