• 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 
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 (auto 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     return (stepNum_ < MAX_TIMERECORD_STEP_NUM && step < stepNum_);
63 }
64 
IsOpen() const65 bool PerformanceAnalysis::IsOpen() const
66 {
67     return isOpen_;
68 }
69 
OpenPerformanceAnalysis()70 void PerformanceAnalysis::OpenPerformanceAnalysis()
71 {
72     isOpen_ = true;
73 }
74 
ClosePerformanceAnalysis()75 void PerformanceAnalysis::ClosePerformanceAnalysis()
76 {
77     isOpen_ = false;
78 }
79 
InsertTimeRecord(const TimePair & timePair,uint32_t step)80 bool PerformanceAnalysis::InsertTimeRecord(const TimePair &timePair, uint32_t step)
81 {
82     if (!IsStepValid(step)) {
83         return false;
84     }
85     timeRecordData_.timeInfo[step] = timePair;
86     return true;
87 }
88 
GetTimeRecord(uint32_t step,TimePair & timePair) const89 bool PerformanceAnalysis::GetTimeRecord(uint32_t step, TimePair &timePair) const
90 {
91     if (!IsStepValid(step)) {
92         return false;
93     }
94     timePair = timeRecordData_.timeInfo[step];
95     return true;
96 }
97 
TimeRecordStart()98 void PerformanceAnalysis::TimeRecordStart()
99 {
100     if (!IsOpen()) {
101         return;
102     }
103     StepTimeRecordStart(0);
104 }
105 
TimeRecordEnd()106 void PerformanceAnalysis::TimeRecordEnd()
107 {
108     if (!IsOpen()) {
109         return;
110     }
111     StepTimeRecordEnd(0);
112 }
113 
StepTimeRecordStart(uint32_t step)114 void PerformanceAnalysis::StepTimeRecordStart(uint32_t step)
115 {
116     if (!IsOpen()) {
117         return;
118     }
119     if (!IsStepValid(step)) {
120         return;
121     }
122     TimePair timePair = {0, 0};
123     uint64_t curTime = 0;
124     int errCode = OS::GetCurrentSysTimeInMicrosecond(curTime);
125     if (errCode != E_OK) {
126         LOGE("[performance_analysis] GetCurrentSysTimeInMicrosecond fail");
127     } else {
128         timePair.startTime = curTime;
129         LOGD("[performance_analysis] StepTimeRecordStart step:%" PRIu32 ", curTime:%" PRIu64, step, curTime);
130         (void)InsertTimeRecord(timePair, step);
131     }
132 }
133 
StepTimeRecordEnd(uint32_t step)134 void PerformanceAnalysis::StepTimeRecordEnd(uint32_t step)
135 {
136     if (!IsOpen()) {
137         return;
138     }
139     if (!IsStepValid(step)) {
140         return;
141     }
142     TimePair timePair = {0, 0};
143     bool errCode = GetTimeRecord(step, timePair);
144     if (!errCode) {
145         return;
146     }
147     (void)InsertTimeRecord({0, 0}, step);
148 
149     uint64_t curTime = 0;
150     (void)OS::GetCurrentSysTimeInMicrosecond(curTime);
151     timePair.endTime = curTime;
152     LOGD("[performance_analysis] StepTimeRecordEnd step:%" PRIu32 ", curTime:%" PRIu64, step, curTime);
153 
154     if ((timePair.endTime < timePair.startTime) || (timePair.startTime == 0) || (timePair.endTime == 0)) {
155         return;
156     }
157     Timestamp offset = timePair.endTime - timePair.startTime;
158     if (stepTimeRecordInfo_[step].max < offset) {
159         stepTimeRecordInfo_[step].max = offset;
160     }
161     if (offset < stepTimeRecordInfo_[step].min) {
162         stepTimeRecordInfo_[step].min = offset;
163     }
164     counts_[step]++;
165     if (counts_[step] == 0) {
166         stepTimeRecordInfo_[step].average = 0;
167         return;
168     }
169     stepTimeRecordInfo_[step].average += (static_cast<float>(offset) -
170         stepTimeRecordInfo_[step].average) / counts_[step];
171 }
172 
GetStatistics()173 std::string PerformanceAnalysis::GetStatistics()
174 {
175     std::string result;
176     for (size_t i = 0; i < stepTimeRecordInfo_.size(); i++) {
177         if (stepTimeRecordInfo_[i].max != 0) {
178             result += "\nstep : " + std::to_string(i) + "\n";
179             result += "max:                 " + std::to_string(stepTimeRecordInfo_[i].max) + "\n";
180             result += "min:                 " + std::to_string(stepTimeRecordInfo_[i].min) + "\n";
181             result += "average:             " +
182                 std::to_string(static_cast<uint64_t>(stepTimeRecordInfo_[i].average)) + "\n";
183             result += "count:               " + std::to_string(counts_[i]) + "\n";
184         }
185     }
186     OutStatistics();
187     Clear();
188     return result;
189 }
190 
OutStatistics()191 void PerformanceAnalysis::OutStatistics()
192 {
193     std::string addrStatistics = STATISTICAL_DATA_FILE_NAME_HEADER + fileID_ + CSV_FILE_EXTENSION;
194     outFile.open(addrStatistics, std::ios_base::app);
195     if (!outFile.is_open()) {
196         return;
197     }
198     // This part filters the zeros data
199     outFile << "stepNum, maxTime(us), minTime(us), averageTime(us), count,\n";
200     for (size_t i = 0; i < stepTimeRecordInfo_.size(); i++) { // output to performance file
201         if (stepTimeRecordInfo_[i].max != 0) {
202             outFile << i << "," << stepTimeRecordInfo_[i].max<< "," << stepTimeRecordInfo_[i].min
203                 << "," << stepTimeRecordInfo_[i].average << "," << counts_[i] << "," << "\n";
204         }
205     }
206     LOGD("outFile success and exit!");
207     outFile.close();
208 }
209 
Clear()210 void PerformanceAnalysis::Clear()
211 {
212     counts_.clear();
213     timeRecordData_.timeInfo.clear();
214     stepTimeRecordInfo_.clear();
215     counts_.resize(stepNum_);
216     timeRecordData_.timeInfo.resize(stepNum_);
217     stepTimeRecordInfo_.resize(stepNum_);
218     for (auto &iter : stepTimeRecordInfo_) {
219         iter.max = 0;
220         iter.min = ULLONG_MAX;
221         iter.average = 0;
222     }
223     fileID_ = std::string(DEFAULT_FILE_NAME) + std::to_string(fileNumber_);
224 }
225 
SetFileNumber(const std::string & FileID)226 void PerformanceAnalysis::SetFileNumber(const std::string &FileID)
227 {
228     fileID_ = FileID;
229 }
230 }  // namespace DistributedDB
231