3d1d3bbb创建于 2022年10月29日历史提交
/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <sstream>
#include <cstdio>
#include <cstring>
#include <climits>
#include "securec.h"
#include "include/sp_utils.h"
#include "include/CPU.h"
namespace OHOS {
namespace SmartPerf {
std::map<std::string, std::string> CPU::ItemData()
{
    std::map<std::string, std::string> result;
    if (mCpuNum < 0) {
        GetCpuNum();
    }
    std::vector<float> workloads = GetCpuLoad();
    std::string cpuLoadsStr;
    std::string cpuFreqStr;
    for (size_t i = 0; i < workloads.size(); i++) {
        cpuLoadsStr = std::to_string(workloads[i]);
        cpuFreqStr = std::to_string(GetCpuFreq(i));
        result["cpu" + std::to_string(i) + "Load"] = cpuLoadsStr;
        result["cpu" + std::to_string(i) + "Frequency"] = cpuFreqStr;
    }
    return result;
}
int CPU::GetCpuNum()
{
    int cpuNum = 0;
    while (true) {
        std::stringstream cpuNodeStr;
        cpuNodeStr << cpuBasePath.c_str() << "/cpu" << cpuNum;
        if (!SPUtils::FileAccess(cpuNodeStr.str())) {
            break;
        }
        ++cpuNum;
    }
    return mCpuNum = cpuNum;
}
int CPU::GetCpuFreq(int cpuId)
{
    std::string curFreq = "-1";
    SPUtils::LoadFile(CpuScalingCurFreq(cpuId), curFreq);
    return atoi(curFreq.c_str());
}
std::vector<float> CPU::GetCpuLoad()
{
    if (mCpuNum <= 0) {
        std::vector<float> workload;
        return workload;
    }
    std::vector<float> workload;

    static char preBuffer[10][256] = {"\0", "\0", "\0", "\0", "\0", "\0", "\0", "\0", "\0", "\0"};
    if (!SPUtils::FileAccess(procStat)) {
        return workload;
    }
    char realPath[PATH_MAX] = {0x00};
    if (realpath(procStat.c_str(), realPath) == nullptr) {
        std::cout << "" << std::endl;
    }
    FILE *fp = fopen(realPath, "r");
    if (fp == nullptr) {
        for (int i = 0; i <= mCpuNum; ++i) {
            workload.push_back(-1.0f);
        }
        return workload;
    }
    char buffer[1024];
    buffer[0] = '\0';
    int line = 0;
    while (fgets(buffer, sizeof(buffer), fp) != nullptr) {
        const int zeroPos = 0;
        const int firstPos = 1;
        const int secondPos = 2;
        const int length = 3;
        if (strlen(buffer) >= length && buffer[zeroPos] == 'c' && buffer[firstPos] == 'p' && buffer[secondPos] == 'u' &&
            line != 0) {
            float b = CacWorkload(buffer, preBuffer[line]);
            workload.push_back(b);
            if (snprintf_s(preBuffer[line], sizeof(preBuffer[line]), sizeof(preBuffer[line]), "%s", buffer) < 0) {
                std::cout << "snprintf_s turn fail" << std::endl;
            }
        }
        ++line;

        if (line >= mCpuNum + 1) {
            break;
        }
    }
    if (fclose(fp) == EOF) {
        return workload;
    }

    return workload;
}

float CPU::CacWorkload(const char *buffer, const char *preBuffer) const
{
    const size_t defaultIndex = 4;
    const size_t defaultShift = 10;
    const char defaultStart = '0';
    const char defaultEnd = '9';

    size_t preLen = strlen(preBuffer);
    size_t len = strlen(buffer);
    if (preLen == 0 || len == 0) {
        return -1.0f;
    }
    size_t time[10] = {0};
    size_t preTime[10] = {0};
    size_t cnt = 0;

    for (size_t i = defaultIndex; i < len; ++i) {
        size_t tmp = 0;
        if (buffer[i] < defaultStart || buffer[i] > defaultEnd) {
            continue;
        }
        while (buffer[i] >= defaultStart && buffer[i] <= defaultEnd) {
            tmp = tmp * defaultShift + (buffer[i] - defaultStart);
            i++;
        }
        time[cnt++] = tmp;
    }

    size_t preCnt = 0;
    for (size_t i = defaultIndex; i < preLen; ++i) {
        size_t tmp = 0;
        if (preBuffer[i] < defaultStart || preBuffer[i] > defaultEnd) {
            continue;
        }
        while (preBuffer[i] >= defaultStart && preBuffer[i] <= defaultEnd) {
            tmp = tmp * defaultShift + (preBuffer[i] - defaultStart);
            i++;
        }
        preTime[preCnt++] = tmp;
    }

    size_t user = time[0] + time[1] - preTime[0] - preTime[1];
    size_t sys = time[2] - preTime[2];
    size_t idle = time[3] - preTime[3];
    size_t iowait = time[4] - preTime[4];
    size_t irq = time[5] + time[6] - preTime[5] - preTime[6];
    size_t total = user + sys + idle + iowait + irq;

    double perUser = std::atof(std::to_string(user * 100.0 / total).c_str());
    double perSys = std::atof(std::to_string(sys * 100.0 / total).c_str());
    double periowait = std::atof(std::to_string(iowait * 100.0 / total).c_str());
    double perirq = std::atof(std::to_string(irq * 100.0 / total).c_str());

    double workload = perUser + perSys + periowait + perirq;

    return static_cast<float>(workload);
}
}
}