1b0e7dd80Sopenharmony_ci/*
2b0e7dd80Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
3b0e7dd80Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4b0e7dd80Sopenharmony_ci * you may not use this file except in compliance with the License.
5b0e7dd80Sopenharmony_ci * You may obtain a copy of the License at
6b0e7dd80Sopenharmony_ci *
7b0e7dd80Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8b0e7dd80Sopenharmony_ci *
9b0e7dd80Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10b0e7dd80Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11b0e7dd80Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12b0e7dd80Sopenharmony_ci * See the License for the specific language governing permissions and
13b0e7dd80Sopenharmony_ci * limitations under the License.
14b0e7dd80Sopenharmony_ci */
15b0e7dd80Sopenharmony_ci
16b0e7dd80Sopenharmony_ci#include "dynamic_buffer.h"
17b0e7dd80Sopenharmony_ci#include "common_utils.h"
18b0e7dd80Sopenharmony_ci
19b0e7dd80Sopenharmony_ci#include <fstream>
20b0e7dd80Sopenharmony_ci#include <cmath>
21b0e7dd80Sopenharmony_ci
22b0e7dd80Sopenharmony_cinamespace OHOS {
23b0e7dd80Sopenharmony_cinamespace HiviewDFX {
24b0e7dd80Sopenharmony_cinamespace Hitrace {
25b0e7dd80Sopenharmony_ci
26b0e7dd80Sopenharmony_cinamespace {
27b0e7dd80Sopenharmony_ciconstexpr int EXPANSION_SIZE = 1024 * 6; // 6M
28b0e7dd80Sopenharmony_ciconstexpr int LOW_THRESHOLD = 400 * 1024; // 400kb
29b0e7dd80Sopenharmony_ciconstexpr int BASE_SIZE = 12 * 1024; // 12M
30b0e7dd80Sopenharmony_ciconstexpr int EXPONENT = 2;
31b0e7dd80Sopenharmony_ciconstexpr int PAGE_KB = 4;
32b0e7dd80Sopenharmony_ci} // namespace
33b0e7dd80Sopenharmony_ci
34b0e7dd80Sopenharmony_cibool DynamicBuffer::GetPerCpuStatsInfo(const size_t cpuIndex, TraceStatsInfo& traceStats)
35b0e7dd80Sopenharmony_ci{
36b0e7dd80Sopenharmony_ci    std::string statsPath = traceRootPath + "per_cpu/cpu" + std::to_string(cpuIndex) + "/stats";
37b0e7dd80Sopenharmony_ci    std::string standardizedPath = CanonicalizeSpecPath(statsPath.c_str());
38b0e7dd80Sopenharmony_ci    std::ifstream inFile;
39b0e7dd80Sopenharmony_ci    inFile.open(standardizedPath.c_str(), std::ios::in);
40b0e7dd80Sopenharmony_ci    if (!inFile.is_open()) {
41b0e7dd80Sopenharmony_ci        return false;
42b0e7dd80Sopenharmony_ci    }
43b0e7dd80Sopenharmony_ci
44b0e7dd80Sopenharmony_ci    std::string line;
45b0e7dd80Sopenharmony_ci    const size_t oldTsPos = 17;
46b0e7dd80Sopenharmony_ci    const size_t nowTsPos = 8;
47b0e7dd80Sopenharmony_ci    const size_t bytesPos = 7;
48b0e7dd80Sopenharmony_ci    while (std::getline(inFile, line)) {
49b0e7dd80Sopenharmony_ci        if ((line.find("oldest event ts: ")) != std::string::npos) {
50b0e7dd80Sopenharmony_ci            traceStats.oldTs = std::stod(line.substr(oldTsPos));
51b0e7dd80Sopenharmony_ci        }
52b0e7dd80Sopenharmony_ci        if ((line.find("now ts: ")) != std::string::npos) {
53b0e7dd80Sopenharmony_ci            traceStats.nowTs = std::stod(line.substr(nowTsPos));
54b0e7dd80Sopenharmony_ci        }
55b0e7dd80Sopenharmony_ci        if ((line.find("bytes: ")) != std::string::npos) {
56b0e7dd80Sopenharmony_ci            traceStats.bytes = std::stod(line.substr(bytesPos));
57b0e7dd80Sopenharmony_ci        }
58b0e7dd80Sopenharmony_ci    }
59b0e7dd80Sopenharmony_ci    inFile.close();
60b0e7dd80Sopenharmony_ci    return true;
61b0e7dd80Sopenharmony_ci}
62b0e7dd80Sopenharmony_ci
63b0e7dd80Sopenharmony_civoid DynamicBuffer::UpdateTraceLoad()
64b0e7dd80Sopenharmony_ci{
65b0e7dd80Sopenharmony_ci    if (!allTraceStats.empty()) {
66b0e7dd80Sopenharmony_ci        allTraceStats.clear();
67b0e7dd80Sopenharmony_ci    }
68b0e7dd80Sopenharmony_ci    totalCpusLoad = 0.0;
69b0e7dd80Sopenharmony_ci    totalAverage = 0;
70b0e7dd80Sopenharmony_ci    maxAverage = 0;
71b0e7dd80Sopenharmony_ci    for (int i = 0; i < cpuNums; i++) {
72b0e7dd80Sopenharmony_ci        TraceStatsInfo traceStats = {};
73b0e7dd80Sopenharmony_ci        if (!GetPerCpuStatsInfo(i, traceStats)) {
74b0e7dd80Sopenharmony_ci            HILOG_ERROR(LOG_CORE, "GetPerCpuStatsInfo failed.");
75b0e7dd80Sopenharmony_ci            return;
76b0e7dd80Sopenharmony_ci        }
77b0e7dd80Sopenharmony_ci        int duration = floor(traceStats.nowTs - traceStats.oldTs);
78b0e7dd80Sopenharmony_ci        if (duration == 0) {
79b0e7dd80Sopenharmony_ci            HILOG_ERROR(LOG_CORE, "nowTs:%{public}lf, oldTs:%{public}lf", traceStats.nowTs, traceStats.oldTs);
80b0e7dd80Sopenharmony_ci            return;
81b0e7dd80Sopenharmony_ci        }
82b0e7dd80Sopenharmony_ci        traceStats.averageTrace = traceStats.bytes / duration;
83b0e7dd80Sopenharmony_ci        totalAverage += traceStats.averageTrace;
84b0e7dd80Sopenharmony_ci        if (maxAverage < traceStats.averageTrace) {
85b0e7dd80Sopenharmony_ci            maxAverage = traceStats.averageTrace;
86b0e7dd80Sopenharmony_ci        }
87b0e7dd80Sopenharmony_ci        traceStats.freq = pow(traceStats.averageTrace, EXPONENT);
88b0e7dd80Sopenharmony_ci        totalCpusLoad += traceStats.freq;
89b0e7dd80Sopenharmony_ci        allTraceStats.push_back(traceStats);
90b0e7dd80Sopenharmony_ci    }
91b0e7dd80Sopenharmony_ci}
92b0e7dd80Sopenharmony_ci
93b0e7dd80Sopenharmony_civoid DynamicBuffer::CalculateBufferSize(std::vector<int>& result)
94b0e7dd80Sopenharmony_ci{
95b0e7dd80Sopenharmony_ci    UpdateTraceLoad();
96b0e7dd80Sopenharmony_ci    if (static_cast<int>(allTraceStats.size()) != cpuNums) {
97b0e7dd80Sopenharmony_ci        return;
98b0e7dd80Sopenharmony_ci    }
99b0e7dd80Sopenharmony_ci    HILOG_DEBUG(LOG_CORE, "hitrace: average = %{public}d.", totalAverage / cpuNums);
100b0e7dd80Sopenharmony_ci
101b0e7dd80Sopenharmony_ci    int totalBonus = 0;
102b0e7dd80Sopenharmony_ci    if (maxAverage > LOW_THRESHOLD) {
103b0e7dd80Sopenharmony_ci        totalBonus = EXPANSION_SIZE * cpuNums;
104b0e7dd80Sopenharmony_ci    }
105b0e7dd80Sopenharmony_ci
106b0e7dd80Sopenharmony_ci    for (int i = 0; i < cpuNums; i++) {
107b0e7dd80Sopenharmony_ci        int newSize = BASE_SIZE + floor((allTraceStats[i].freq / totalCpusLoad) * totalBonus);
108b0e7dd80Sopenharmony_ci        newSize = newSize / PAGE_KB * PAGE_KB;
109b0e7dd80Sopenharmony_ci        result.push_back(newSize);
110b0e7dd80Sopenharmony_ci    }
111b0e7dd80Sopenharmony_ci}
112b0e7dd80Sopenharmony_ci
113b0e7dd80Sopenharmony_ci} // Hitrace
114b0e7dd80Sopenharmony_ci} // HiviewDFX
115b0e7dd80Sopenharmony_ci} // OHOS