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 "dynamic_buffer.h"
17 #include "common_utils.h"
18 
19 #include <fstream>
20 #include <cmath>
21 
22 namespace OHOS {
23 namespace HiviewDFX {
24 namespace Hitrace {
25 
26 namespace {
27 constexpr int EXPANSION_SIZE = 1024 * 6; // 6M
28 constexpr int LOW_THRESHOLD = 400 * 1024; // 400kb
29 constexpr int BASE_SIZE = 12 * 1024; // 12M
30 constexpr int EXPONENT = 2;
31 constexpr int PAGE_KB = 4;
32 } // namespace
33 
GetPerCpuStatsInfo(const size_t cpuIndex,TraceStatsInfo & traceStats)34 bool DynamicBuffer::GetPerCpuStatsInfo(const size_t cpuIndex, TraceStatsInfo& traceStats)
35 {
36     std::string statsPath = traceRootPath + "per_cpu/cpu" + std::to_string(cpuIndex) + "/stats";
37     std::string standardizedPath = CanonicalizeSpecPath(statsPath.c_str());
38     std::ifstream inFile;
39     inFile.open(standardizedPath.c_str(), std::ios::in);
40     if (!inFile.is_open()) {
41         return false;
42     }
43 
44     std::string line;
45     const size_t oldTsPos = 17;
46     const size_t nowTsPos = 8;
47     const size_t bytesPos = 7;
48     while (std::getline(inFile, line)) {
49         if ((line.find("oldest event ts: ")) != std::string::npos) {
50             traceStats.oldTs = std::stod(line.substr(oldTsPos));
51         }
52         if ((line.find("now ts: ")) != std::string::npos) {
53             traceStats.nowTs = std::stod(line.substr(nowTsPos));
54         }
55         if ((line.find("bytes: ")) != std::string::npos) {
56             traceStats.bytes = std::stod(line.substr(bytesPos));
57         }
58     }
59     inFile.close();
60     return true;
61 }
62 
UpdateTraceLoad()63 void DynamicBuffer::UpdateTraceLoad()
64 {
65     if (!allTraceStats.empty()) {
66         allTraceStats.clear();
67     }
68     totalCpusLoad = 0.0;
69     totalAverage = 0;
70     maxAverage = 0;
71     for (int i = 0; i < cpuNums; i++) {
72         TraceStatsInfo traceStats = {};
73         if (!GetPerCpuStatsInfo(i, traceStats)) {
74             HILOG_ERROR(LOG_CORE, "GetPerCpuStatsInfo failed.");
75             return;
76         }
77         int duration = floor(traceStats.nowTs - traceStats.oldTs);
78         if (duration == 0) {
79             HILOG_ERROR(LOG_CORE, "nowTs:%{public}lf, oldTs:%{public}lf", traceStats.nowTs, traceStats.oldTs);
80             return;
81         }
82         traceStats.averageTrace = traceStats.bytes / duration;
83         totalAverage += traceStats.averageTrace;
84         if (maxAverage < traceStats.averageTrace) {
85             maxAverage = traceStats.averageTrace;
86         }
87         traceStats.freq = pow(traceStats.averageTrace, EXPONENT);
88         totalCpusLoad += traceStats.freq;
89         allTraceStats.push_back(traceStats);
90     }
91 }
92 
CalculateBufferSize(std::vector<int> & result)93 void DynamicBuffer::CalculateBufferSize(std::vector<int>& result)
94 {
95     UpdateTraceLoad();
96     if (static_cast<int>(allTraceStats.size()) != cpuNums) {
97         return;
98     }
99     HILOG_DEBUG(LOG_CORE, "hitrace: average = %{public}d.", totalAverage / cpuNums);
100 
101     int totalBonus = 0;
102     if (maxAverage > LOW_THRESHOLD) {
103         totalBonus = EXPANSION_SIZE * cpuNums;
104     }
105 
106     for (int i = 0; i < cpuNums; i++) {
107         int newSize = BASE_SIZE + floor((allTraceStats[i].freq / totalCpusLoad) * totalBonus);
108         newSize = newSize / PAGE_KB * PAGE_KB;
109         result.push_back(newSize);
110     }
111 }
112 
113 } // Hitrace
114 } // HiviewDFX
115 } // OHOS