148f512ceSopenharmony_ci/*
248f512ceSopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
348f512ceSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
448f512ceSopenharmony_ci * you may not use this file except in compliance with the License.
548f512ceSopenharmony_ci * You may obtain a copy of the License at
648f512ceSopenharmony_ci *
748f512ceSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
848f512ceSopenharmony_ci *
948f512ceSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1048f512ceSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1148f512ceSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1248f512ceSopenharmony_ci * See the License for the specific language governing permissions and
1348f512ceSopenharmony_ci * limitations under the License.
1448f512ceSopenharmony_ci */
1548f512ceSopenharmony_ci
1648f512ceSopenharmony_ci#define HILOG_TAG "Stat"
1748f512ceSopenharmony_ci
1848f512ceSopenharmony_ci#include "subcommand_stat.h"
1948f512ceSopenharmony_ci
2048f512ceSopenharmony_ci#include <csignal>
2148f512ceSopenharmony_ci#include <iostream>
2248f512ceSopenharmony_ci#include <memory>
2348f512ceSopenharmony_ci
2448f512ceSopenharmony_ci#include "debug_logger.h"
2548f512ceSopenharmony_ci#include "hiperf_hilog.h"
2648f512ceSopenharmony_ci#include "utilities.h"
2748f512ceSopenharmony_ci
2848f512ceSopenharmony_ciconst uint16_t ONE_HUNDRED = 100;
2948f512ceSopenharmony_ciconst uint16_t THOUSNADS_SEPARATOR = 3;
3048f512ceSopenharmony_cinamespace OHOS {
3148f512ceSopenharmony_cinamespace Developtools {
3248f512ceSopenharmony_cinamespace HiPerf {
3348f512ceSopenharmony_cistatic std::map<pid_t, ThreadInfos> thread_map_;
3448f512ceSopenharmony_cistatic bool g_reportCpuFlag = false;
3548f512ceSopenharmony_cistatic bool g_reportThreadFlag = false;
3648f512ceSopenharmony_cistatic VirtualRuntime g_runtimeInstance;
3748f512ceSopenharmony_civoid SubCommandStat::DumpOptions() const
3848f512ceSopenharmony_ci{
3948f512ceSopenharmony_ci    printf("DumpOptions:\n");
4048f512ceSopenharmony_ci    printf(" targetSystemWide:\t%s\n", targetSystemWide_ ? "true" : "false");
4148f512ceSopenharmony_ci    printf(" selectCpus:\t%s\n", VectorToString(selectCpus_).c_str());
4248f512ceSopenharmony_ci    printf(" timeStopSec:\t%f sec\n", timeStopSec_);
4348f512ceSopenharmony_ci    printf(" timeReportMs:\t%d ms\n", timeReportMs_);
4448f512ceSopenharmony_ci    printf(" selectEvents:\t%s\n", VectorToString(selectEvents_).c_str());
4548f512ceSopenharmony_ci    printf(" selectGroups:\t%s\n", VectorToString(selectGroups_).c_str());
4648f512ceSopenharmony_ci    printf(" noCreateNew:\t%s\n", noCreateNew_ ? "true" : "false");
4748f512ceSopenharmony_ci    printf(" appPackage:\t%s\n", appPackage_.c_str());
4848f512ceSopenharmony_ci    printf(" checkAppMs_:\t%d\n", checkAppMs_);
4948f512ceSopenharmony_ci    printf(" selectPids:\t%s\n", VectorToString(selectPids_).c_str());
5048f512ceSopenharmony_ci    printf(" selectTids:\t%s\n", VectorToString(selectTids_).c_str());
5148f512ceSopenharmony_ci    printf(" restart:\t%s\n", restart_ ? "true" : "false");
5248f512ceSopenharmony_ci    printf(" perCore:\t%s\n", perCpus_ ? "true" : "false");
5348f512ceSopenharmony_ci    printf(" perTread:\t%s\n", perThreads_ ? "true" : "false");
5448f512ceSopenharmony_ci    printf(" verbose:\t%s\n", verboseReport_ ? "true" : "false");
5548f512ceSopenharmony_ci}
5648f512ceSopenharmony_ci
5748f512ceSopenharmony_cibool SubCommandStat::ParseOption(std::vector<std::string> &args)
5848f512ceSopenharmony_ci{
5948f512ceSopenharmony_ci    if (args.size() == 1 and args[0] == "-h") {
6048f512ceSopenharmony_ci        args.clear();
6148f512ceSopenharmony_ci        helpOption_ = true;
6248f512ceSopenharmony_ci        PrintUsage();
6348f512ceSopenharmony_ci        return true;
6448f512ceSopenharmony_ci    }
6548f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "-a", targetSystemWide_)) {
6648f512ceSopenharmony_ci        HLOGD("get option -a failed");
6748f512ceSopenharmony_ci        return false;
6848f512ceSopenharmony_ci    }
6948f512ceSopenharmony_ci    if (targetSystemWide_ && !IsSupportNonDebuggableApp()) {
7048f512ceSopenharmony_ci        HLOGD("-a option needs root privilege for system wide profiling.");
7148f512ceSopenharmony_ci        printf("-a option needs root privilege for system wide profiling.\n");
7248f512ceSopenharmony_ci        return false;
7348f512ceSopenharmony_ci    }
7448f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "-c", selectCpus_)) {
7548f512ceSopenharmony_ci        HLOGD("get option -c failed");
7648f512ceSopenharmony_ci        return false;
7748f512ceSopenharmony_ci    }
7848f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "-d", timeStopSec_)) {
7948f512ceSopenharmony_ci        HLOGD("get option -d failed");
8048f512ceSopenharmony_ci        return false;
8148f512ceSopenharmony_ci    }
8248f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "-i", timeReportMs_)) {
8348f512ceSopenharmony_ci        HLOGD("get option -i failed");
8448f512ceSopenharmony_ci        return false;
8548f512ceSopenharmony_ci    }
8648f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "-e", selectEvents_)) {
8748f512ceSopenharmony_ci        HLOGD("get option -e failed");
8848f512ceSopenharmony_ci        return false;
8948f512ceSopenharmony_ci    }
9048f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "-g", selectGroups_)) {
9148f512ceSopenharmony_ci        HLOGD("get option -g failed");
9248f512ceSopenharmony_ci        return false;
9348f512ceSopenharmony_ci    }
9448f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "--no-inherit", noCreateNew_)) {
9548f512ceSopenharmony_ci        HLOGD("get option --no-inherit failed");
9648f512ceSopenharmony_ci        return false;
9748f512ceSopenharmony_ci    }
9848f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "--app", appPackage_)) {
9948f512ceSopenharmony_ci        HLOGD("get option --app failed");
10048f512ceSopenharmony_ci        return false;
10148f512ceSopenharmony_ci    }
10248f512ceSopenharmony_ci    if (!IsExistDebugByApp(appPackage_)) {
10348f512ceSopenharmony_ci        return false;
10448f512ceSopenharmony_ci    }
10548f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "--chkms", checkAppMs_)) {
10648f512ceSopenharmony_ci        return false;
10748f512ceSopenharmony_ci    }
10848f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "-p", selectPids_)) {
10948f512ceSopenharmony_ci        HLOGD("get option -p failed");
11048f512ceSopenharmony_ci        return false;
11148f512ceSopenharmony_ci    }
11248f512ceSopenharmony_ci    if (!IsExistDebugByPid(selectPids_)) {
11348f512ceSopenharmony_ci        return false;
11448f512ceSopenharmony_ci    }
11548f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "-t", selectTids_)) {
11648f512ceSopenharmony_ci        HLOGD("get option -t failed");
11748f512ceSopenharmony_ci        return false;
11848f512ceSopenharmony_ci    }
11948f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "--restart", restart_)) {
12048f512ceSopenharmony_ci        HLOGD("get option --restart failed");
12148f512ceSopenharmony_ci        return false;
12248f512ceSopenharmony_ci    }
12348f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "--per-core", perCpus_)) {
12448f512ceSopenharmony_ci        HLOGD("get option --per-core failed");
12548f512ceSopenharmony_ci        return false;
12648f512ceSopenharmony_ci    }
12748f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "--per-thread", perThreads_)) {
12848f512ceSopenharmony_ci        HLOGD("get option --per-thread failed");
12948f512ceSopenharmony_ci        return false;
13048f512ceSopenharmony_ci    }
13148f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "--verbose", verboseReport_)) {
13248f512ceSopenharmony_ci        HLOGD("get option --verbose failed");
13348f512ceSopenharmony_ci        return false;
13448f512ceSopenharmony_ci    }
13548f512ceSopenharmony_ci    return ParseSpecialOption(args);
13648f512ceSopenharmony_ci}
13748f512ceSopenharmony_ci
13848f512ceSopenharmony_cibool SubCommandStat::ParseSpecialOption(std::vector<std::string> &args)
13948f512ceSopenharmony_ci{
14048f512ceSopenharmony_ci    if (!Option::GetOptionTrackedCommand(args, trackedCommand_)) {
14148f512ceSopenharmony_ci        HLOGD("get cmd failed");
14248f512ceSopenharmony_ci        return false;
14348f512ceSopenharmony_ci    }
14448f512ceSopenharmony_ci    if (!args.empty()) {
14548f512ceSopenharmony_ci        HLOGD("redundant option(s)");
14648f512ceSopenharmony_ci        return false;
14748f512ceSopenharmony_ci    }
14848f512ceSopenharmony_ci    return true;
14948f512ceSopenharmony_ci}
15048f512ceSopenharmony_ci
15148f512ceSopenharmony_civoid SubCommandStat::PrintUsage()
15248f512ceSopenharmony_ci{
15348f512ceSopenharmony_ci    printf("%s\n", Help().c_str());
15448f512ceSopenharmony_ci}
15548f512ceSopenharmony_ci
15648f512ceSopenharmony_civoid SubCommandStat::SetReportFlags(bool cpuFlag, bool threadFlag)
15748f512ceSopenharmony_ci{
15848f512ceSopenharmony_ci    g_reportCpuFlag = cpuFlag;
15948f512ceSopenharmony_ci    g_reportThreadFlag = threadFlag;
16048f512ceSopenharmony_ci}
16148f512ceSopenharmony_ci
16248f512ceSopenharmony_civoid SubCommandStat::Report(const std::map<std::string, std::unique_ptr<PerfEvents::CountEvent>> &countEvents)
16348f512ceSopenharmony_ci{
16448f512ceSopenharmony_ci    bool isNeedPerCpuTid = false;
16548f512ceSopenharmony_ci    for (auto it = countEvents.begin(); it != countEvents.end(); ++it) {
16648f512ceSopenharmony_ci        if (!(it->second->summaries.empty())) {
16748f512ceSopenharmony_ci            isNeedPerCpuTid = true;
16848f512ceSopenharmony_ci            break;
16948f512ceSopenharmony_ci        }
17048f512ceSopenharmony_ci    }
17148f512ceSopenharmony_ci    if (isNeedPerCpuTid) {
17248f512ceSopenharmony_ci        PrintPerHead();
17348f512ceSopenharmony_ci        ReportDetailInfos(countEvents);
17448f512ceSopenharmony_ci    } else {
17548f512ceSopenharmony_ci        ReportNormal(countEvents);
17648f512ceSopenharmony_ci    }
17748f512ceSopenharmony_ci}
17848f512ceSopenharmony_ci
17948f512ceSopenharmony_civoid SubCommandStat::PrintPerHead()
18048f512ceSopenharmony_ci{
18148f512ceSopenharmony_ci    // print head
18248f512ceSopenharmony_ci    if (g_reportCpuFlag && g_reportThreadFlag) {
18348f512ceSopenharmony_ci        printf(" %24s  %-30s | %-30s %10s %10s %10s | %-32s | %s\n", "count", "event_name", "thread_name",
18448f512ceSopenharmony_ci               "pid", "tid", "coreid", "comment", "coverage");
18548f512ceSopenharmony_ci        return;
18648f512ceSopenharmony_ci    }
18748f512ceSopenharmony_ci    if (g_reportCpuFlag) {
18848f512ceSopenharmony_ci        printf(" %24s  %-30s | %10s | %-32s | %s\n", "count", "event_name", "coreid", "comment", "coverage");
18948f512ceSopenharmony_ci        return;
19048f512ceSopenharmony_ci    }
19148f512ceSopenharmony_ci    printf(" %24s  %-30s | %-30s %10s %10s | %-32s | %s\n", "count", "event_name", "thread_name", "pid", "tid",
19248f512ceSopenharmony_ci           "comment", "coverage");
19348f512ceSopenharmony_ci    return;
19448f512ceSopenharmony_ci}
19548f512ceSopenharmony_ci
19648f512ceSopenharmony_civoid SubCommandStat::PrintPerValue(const std::unique_ptr<PerfEvents::ReportSum> &reportSum, const float &ratio,
19748f512ceSopenharmony_ci                                   std::string &configName)
19848f512ceSopenharmony_ci{
19948f512ceSopenharmony_ci    if (reportSum == nullptr) {
20048f512ceSopenharmony_ci        return;
20148f512ceSopenharmony_ci    }
20248f512ceSopenharmony_ci    // print value
20348f512ceSopenharmony_ci    std::string strEventCount = std::to_string(reportSum->eventCountSum);
20448f512ceSopenharmony_ci    for (size_t i = strEventCount.size() >= 1 ? strEventCount.size() - 1 : 0, j = 1; i > 0; --i, ++j) {
20548f512ceSopenharmony_ci        if (j == THOUSNADS_SEPARATOR) {
20648f512ceSopenharmony_ci            j = 0;
20748f512ceSopenharmony_ci            strEventCount.insert(strEventCount.begin() + i, ',');
20848f512ceSopenharmony_ci        }
20948f512ceSopenharmony_ci    }
21048f512ceSopenharmony_ci
21148f512ceSopenharmony_ci    std::string commentStr;
21248f512ceSopenharmony_ci    MakeComments(reportSum, commentStr);
21348f512ceSopenharmony_ci
21448f512ceSopenharmony_ci    if (g_reportCpuFlag && g_reportThreadFlag) {
21548f512ceSopenharmony_ci        printf(" %24s  %-30s | %-30s %10d %10d %10d | %-32s | (%.0lf%%)\n", strEventCount.c_str(), configName.c_str(),
21648f512ceSopenharmony_ci               reportSum->threadName.c_str(), reportSum->pid, reportSum->tid, reportSum->cpu, commentStr.c_str(),
21748f512ceSopenharmony_ci               reportSum->scaleSum * ratio);
21848f512ceSopenharmony_ci    } else if (g_reportCpuFlag) {
21948f512ceSopenharmony_ci        printf(" %24s  %-30s | %10d | %-32s | (%.0lf%%)\n", strEventCount.c_str(), configName.c_str(),
22048f512ceSopenharmony_ci               reportSum->cpu, commentStr.c_str(), reportSum->scaleSum * ratio);
22148f512ceSopenharmony_ci    } else {
22248f512ceSopenharmony_ci        printf(" %24s  %-30s | %-30s %10d %10d | %-32s | (%.0lf%%)\n", strEventCount.c_str(), configName.c_str(),
22348f512ceSopenharmony_ci               reportSum->threadName.c_str(), reportSum->pid, reportSum->tid, commentStr.c_str(),
22448f512ceSopenharmony_ci               reportSum->scaleSum * ratio);
22548f512ceSopenharmony_ci    }
22648f512ceSopenharmony_ci    fflush(stdout);
22748f512ceSopenharmony_ci}
22848f512ceSopenharmony_ci
22948f512ceSopenharmony_civoid SubCommandStat::InitPerMap(const std::unique_ptr<PerfEvents::ReportSum> &newPerMap,
23048f512ceSopenharmony_ci                                const PerfEvents::Summary &summary, VirtualRuntime& virtualInstance)
23148f512ceSopenharmony_ci{
23248f512ceSopenharmony_ci    CHECK_TRUE(newPerMap == nullptr, NO_RETVAL, 0, "");
23348f512ceSopenharmony_ci    newPerMap->cpu = summary.cpu;
23448f512ceSopenharmony_ci    if (g_reportCpuFlag && !g_reportThreadFlag) {
23548f512ceSopenharmony_ci        return;
23648f512ceSopenharmony_ci    }
23748f512ceSopenharmony_ci    newPerMap->tid = summary.tid;
23848f512ceSopenharmony_ci    newPerMap->pid = thread_map_.find(summary.tid)->second.pid;
23948f512ceSopenharmony_ci    bool isTid = true;
24048f512ceSopenharmony_ci    if (newPerMap->pid == newPerMap->tid) {
24148f512ceSopenharmony_ci        isTid = false;
24248f512ceSopenharmony_ci    }
24348f512ceSopenharmony_ci    newPerMap->threadName = virtualInstance.ReadThreadName(summary.tid, isTid);
24448f512ceSopenharmony_ci}
24548f512ceSopenharmony_ci
24648f512ceSopenharmony_civoid SubCommandStat::GetPerKey(std::string &perKey, const PerfEvents::Summary &summary)
24748f512ceSopenharmony_ci{
24848f512ceSopenharmony_ci    perKey = "";
24948f512ceSopenharmony_ci    if (g_reportCpuFlag) {
25048f512ceSopenharmony_ci        perKey += std::to_string(summary.cpu);
25148f512ceSopenharmony_ci        perKey += "|";
25248f512ceSopenharmony_ci    }
25348f512ceSopenharmony_ci    if (g_reportThreadFlag) {
25448f512ceSopenharmony_ci        perKey += std::to_string(summary.tid);
25548f512ceSopenharmony_ci    }
25648f512ceSopenharmony_ci    return;
25748f512ceSopenharmony_ci}
25848f512ceSopenharmony_ci
25948f512ceSopenharmony_civoid SubCommandStat::ReportDetailInfos(
26048f512ceSopenharmony_ci    const std::map<std::string, std::unique_ptr<PerfEvents::CountEvent>> &countEvents)
26148f512ceSopenharmony_ci{
26248f512ceSopenharmony_ci    std::string perKey = "";
26348f512ceSopenharmony_ci    std::map<std::string, std::unique_ptr<PerfEvents::ReportSum>> perMaps;
26448f512ceSopenharmony_ci    for (auto event = countEvents.begin(); event != countEvents.end(); ++event) {
26548f512ceSopenharmony_ci        if (event->second == nullptr || event->second->eventCount == 0) {
26648f512ceSopenharmony_ci            continue;
26748f512ceSopenharmony_ci        }
26848f512ceSopenharmony_ci        constexpr float ratio {100.0};
26948f512ceSopenharmony_ci        std::string configName = event->first;
27048f512ceSopenharmony_ci        perMaps.clear();
27148f512ceSopenharmony_ci        for (auto &it : event->second->summaries) {
27248f512ceSopenharmony_ci            GetPerKey(perKey, it);
27348f512ceSopenharmony_ci            if (perMaps.count(perKey) == 0) {
27448f512ceSopenharmony_ci                auto perMap = std::make_unique<PerfEvents::ReportSum>(PerfEvents::ReportSum {});
27548f512ceSopenharmony_ci                InitPerMap(perMap, it, g_runtimeInstance);
27648f512ceSopenharmony_ci                perMaps[perKey] = std::move(perMap);
27748f512ceSopenharmony_ci            }
27848f512ceSopenharmony_ci            if (perMaps[perKey] == nullptr) {
27948f512ceSopenharmony_ci                continue;
28048f512ceSopenharmony_ci            }
28148f512ceSopenharmony_ci            perMaps[perKey]->configName = GetDetailComments(event->second, perMaps[perKey]->commentSum,
28248f512ceSopenharmony_ci                                                            it, configName);
28348f512ceSopenharmony_ci            perMaps[perKey]->eventCountSum += it.eventCount;
28448f512ceSopenharmony_ci            if (it.timeRunning < it.timeEnabled && it.timeRunning != 0) {
28548f512ceSopenharmony_ci                perMaps[perKey]->scaleSum = 1 / (static_cast<double>(it.timeEnabled) / it.timeRunning);
28648f512ceSopenharmony_ci            }
28748f512ceSopenharmony_ci        }
28848f512ceSopenharmony_ci        for (auto iper = perMaps.begin(); iper != perMaps.end(); iper++) {
28948f512ceSopenharmony_ci            PrintPerValue(iper->second, ratio, configName);
29048f512ceSopenharmony_ci        }
29148f512ceSopenharmony_ci    }
29248f512ceSopenharmony_ci}
29348f512ceSopenharmony_ci
29448f512ceSopenharmony_civoid SubCommandStat::ReportNormal(
29548f512ceSopenharmony_ci    const std::map<std::string, std::unique_ptr<PerfEvents::CountEvent>> &countEvents)
29648f512ceSopenharmony_ci{
29748f512ceSopenharmony_ci    // print head
29848f512ceSopenharmony_ci    printf(" %24s  %-30s | %-32s | %s\n", "count", "name", "comment", "coverage");
29948f512ceSopenharmony_ci    std::map<std::string, std::string> comments;
30048f512ceSopenharmony_ci    GetComments(countEvents, comments);
30148f512ceSopenharmony_ci    for (auto it = countEvents.begin(); it != countEvents.end(); ++it) {
30248f512ceSopenharmony_ci        double scale = 1.0;
30348f512ceSopenharmony_ci        constexpr float ratio {100.0};
30448f512ceSopenharmony_ci        std::string configName = it->first;
30548f512ceSopenharmony_ci        std::string comment = comments[configName];
30648f512ceSopenharmony_ci        std::string strEventCount = std::to_string(it->second->eventCount);
30748f512ceSopenharmony_ci        for (size_t i = strEventCount.size() >= 1 ? strEventCount.size() - 1 : 0, j = 1; i > 0; --i, ++j) {
30848f512ceSopenharmony_ci            if (j == THOUSNADS_SEPARATOR) {
30948f512ceSopenharmony_ci                strEventCount.insert(strEventCount.begin() + i, ',');
31048f512ceSopenharmony_ci                j = 0;
31148f512ceSopenharmony_ci            }
31248f512ceSopenharmony_ci        }
31348f512ceSopenharmony_ci        if (it->second->timeRunning < it->second->timeEnabled && it->second->timeRunning != 0) {
31448f512ceSopenharmony_ci            scale = 1 / (static_cast<double>(it->second->timeEnabled) / it->second->timeRunning);
31548f512ceSopenharmony_ci        }
31648f512ceSopenharmony_ci        printf(" %24s  %-30s | %-32s | (%.0lf%%)\n", strEventCount.c_str(), configName.c_str(),
31748f512ceSopenharmony_ci               comment.c_str(), scale * ratio);
31848f512ceSopenharmony_ci
31948f512ceSopenharmony_ci        fflush(stdout);
32048f512ceSopenharmony_ci    }
32148f512ceSopenharmony_ci}
32248f512ceSopenharmony_ci
32348f512ceSopenharmony_cibool SubCommandStat::FindEventCount(const std::map<std::string, std::unique_ptr<PerfEvents::CountEvent>> &countEvents,
32448f512ceSopenharmony_ci    const std::string &configName, const __u64 group_id, __u64 &eventCount, double &scale)
32548f512ceSopenharmony_ci{
32648f512ceSopenharmony_ci    auto itr = countEvents.find(configName);
32748f512ceSopenharmony_ci    if (itr != countEvents.end()) {
32848f512ceSopenharmony_ci        eventCount = itr->second->eventCount;
32948f512ceSopenharmony_ci        if (itr->second->id == group_id
33048f512ceSopenharmony_ci            && itr->second->timeRunning < itr->second->timeEnabled
33148f512ceSopenharmony_ci            && itr->second->timeRunning != 0) {
33248f512ceSopenharmony_ci            scale = static_cast<double>(itr->second->timeEnabled) / itr->second->timeRunning;
33348f512ceSopenharmony_ci            return true;
33448f512ceSopenharmony_ci        }
33548f512ceSopenharmony_ci    }
33648f512ceSopenharmony_ci    return false;
33748f512ceSopenharmony_ci}
33848f512ceSopenharmony_ci
33948f512ceSopenharmony_cibool SubCommandStat::FindPerCoreEventCount(PerfEvents::Summary &summary, __u64 &eventCount, double &scale)
34048f512ceSopenharmony_ci{
34148f512ceSopenharmony_ci    eventCount = summary.eventCount;
34248f512ceSopenharmony_ci    if (summary.timeRunning < summary.timeEnabled && summary.timeRunning != 0) {
34348f512ceSopenharmony_ci        scale = static_cast<double>(summary.timeEnabled) / summary.timeRunning;
34448f512ceSopenharmony_ci        return true;
34548f512ceSopenharmony_ci    }
34648f512ceSopenharmony_ci    return false;
34748f512ceSopenharmony_ci}
34848f512ceSopenharmony_ci
34948f512ceSopenharmony_cistd::string SubCommandStat::GetCommentConfigName(
35048f512ceSopenharmony_ci    const std::unique_ptr<PerfEvents::CountEvent> &countEvent, std::string eventName)
35148f512ceSopenharmony_ci{
35248f512ceSopenharmony_ci    std::string commentConfigName = "";
35348f512ceSopenharmony_ci    CHECK_TRUE(countEvent == nullptr || eventName.length() == 0, commentConfigName, 0, "");
35448f512ceSopenharmony_ci    if (countEvent->userOnly) {
35548f512ceSopenharmony_ci        commentConfigName = eventName + ":u";
35648f512ceSopenharmony_ci    } else if (countEvent->kernelOnly) {
35748f512ceSopenharmony_ci        commentConfigName = eventName + ":k";
35848f512ceSopenharmony_ci    } else {
35948f512ceSopenharmony_ci        commentConfigName = eventName;
36048f512ceSopenharmony_ci    }
36148f512ceSopenharmony_ci    return commentConfigName;
36248f512ceSopenharmony_ci}
36348f512ceSopenharmony_ci
36448f512ceSopenharmony_civoid SubCommandStat::MakeComments(const std::unique_ptr<PerfEvents::ReportSum> &reportSum, std::string &commentStr)
36548f512ceSopenharmony_ci{
36648f512ceSopenharmony_ci    CHECK_TRUE(reportSum == nullptr || reportSum->commentSum == 0, NO_RETVAL, 0, "");
36748f512ceSopenharmony_ci    if (reportSum->configName == "sw-task-clock") {
36848f512ceSopenharmony_ci        commentStr = StringPrintf("%lf cpus used", reportSum->commentSum);
36948f512ceSopenharmony_ci        return;
37048f512ceSopenharmony_ci    }
37148f512ceSopenharmony_ci    if (reportSum->configName == "hw-cpu-cycles") {
37248f512ceSopenharmony_ci        commentStr = StringPrintf("%lf GHz", reportSum->commentSum);
37348f512ceSopenharmony_ci        return;
37448f512ceSopenharmony_ci    }
37548f512ceSopenharmony_ci    if (reportSum->configName == "hw-instructions") {
37648f512ceSopenharmony_ci        commentStr = StringPrintf("%lf cycles per instruction", reportSum->commentSum);
37748f512ceSopenharmony_ci        return;
37848f512ceSopenharmony_ci    }
37948f512ceSopenharmony_ci    if (reportSum->configName == "hw-branch-misses") {
38048f512ceSopenharmony_ci        commentStr = StringPrintf("%lf miss rate", reportSum->commentSum);
38148f512ceSopenharmony_ci        return;
38248f512ceSopenharmony_ci    }
38348f512ceSopenharmony_ci
38448f512ceSopenharmony_ci    if (reportSum->commentSum > 1e9) {
38548f512ceSopenharmony_ci        commentStr = StringPrintf("%.3lf G/sec", reportSum->commentSum / 1e9);
38648f512ceSopenharmony_ci        return;
38748f512ceSopenharmony_ci    }
38848f512ceSopenharmony_ci    if (reportSum->commentSum > 1e6) {
38948f512ceSopenharmony_ci        commentStr = StringPrintf("%.3lf M/sec", reportSum->commentSum / 1e6);
39048f512ceSopenharmony_ci        return;
39148f512ceSopenharmony_ci    }
39248f512ceSopenharmony_ci    if (reportSum->commentSum > 1e3) {
39348f512ceSopenharmony_ci        commentStr = StringPrintf("%.3lf K/sec", reportSum->commentSum / 1e3);
39448f512ceSopenharmony_ci        return;
39548f512ceSopenharmony_ci    }
39648f512ceSopenharmony_ci    commentStr = StringPrintf("%.3lf /sec", reportSum->commentSum);
39748f512ceSopenharmony_ci}
39848f512ceSopenharmony_ci
39948f512ceSopenharmony_cistd::string SubCommandStat::GetDetailComments(const std::unique_ptr<PerfEvents::CountEvent> &countEvent,
40048f512ceSopenharmony_ci    double &comment, PerfEvents::Summary &summary, std::string &configName)
40148f512ceSopenharmony_ci{
40248f512ceSopenharmony_ci    double running_time_in_sec = 0;
40348f512ceSopenharmony_ci    double main_scale = 1.0;
40448f512ceSopenharmony_ci    bool findRunningTime = FindPercoreRunningTime(summary, running_time_in_sec, main_scale);
40548f512ceSopenharmony_ci    if (configName == GetCommentConfigName(countEvent, "sw-cpu-clock")) {
40648f512ceSopenharmony_ci        comment = 0;
40748f512ceSopenharmony_ci        return "sw-cpu-clock";
40848f512ceSopenharmony_ci    }
40948f512ceSopenharmony_ci    double scale = 1.0;
41048f512ceSopenharmony_ci    if (summary.timeRunning < summary.timeEnabled && summary.timeRunning != 0) {
41148f512ceSopenharmony_ci        scale = static_cast<double>(summary.timeEnabled) / summary.timeRunning;
41248f512ceSopenharmony_ci    }
41348f512ceSopenharmony_ci    if (configName == GetCommentConfigName(countEvent, "sw-task-clock")) {
41448f512ceSopenharmony_ci        comment += countEvent->usedCpus * scale;
41548f512ceSopenharmony_ci        return "sw-task-clock";
41648f512ceSopenharmony_ci    }
41748f512ceSopenharmony_ci    if (configName == GetCommentConfigName(countEvent, "hw-cpu-cycles")) {
41848f512ceSopenharmony_ci        if (findRunningTime) {
41948f512ceSopenharmony_ci            double hz = 0;
42048f512ceSopenharmony_ci            if (abs(running_time_in_sec) > ALMOST_ZERO) {
42148f512ceSopenharmony_ci                hz = summary.eventCount / (running_time_in_sec / scale);
42248f512ceSopenharmony_ci            }
42348f512ceSopenharmony_ci            comment += hz / 1e9;
42448f512ceSopenharmony_ci        } else {
42548f512ceSopenharmony_ci            comment += 0;
42648f512ceSopenharmony_ci        }
42748f512ceSopenharmony_ci        return "hw-cpu-cycles";
42848f512ceSopenharmony_ci    }
42948f512ceSopenharmony_ci    if (configName == GetCommentConfigName(countEvent, "hw-instructions") && summary.eventCount != 0) {
43048f512ceSopenharmony_ci        double otherScale = 1.0;
43148f512ceSopenharmony_ci        __u64 cpuCyclesCount = 0;
43248f512ceSopenharmony_ci        bool other = FindPerCoreEventCount(summary, cpuCyclesCount, otherScale);
43348f512ceSopenharmony_ci        if (other || (IsMonitoredAtAllTime(otherScale) && IsMonitoredAtAllTime(scale))) {
43448f512ceSopenharmony_ci            comment += static_cast<double>(cpuCyclesCount) / summary.eventCount;
43548f512ceSopenharmony_ci            return "hw-instructions";
43648f512ceSopenharmony_ci        }
43748f512ceSopenharmony_ci    }
43848f512ceSopenharmony_ci    if (configName == GetCommentConfigName(countEvent, "hw-branch-misses")) {
43948f512ceSopenharmony_ci        double otherScale = 1.0;
44048f512ceSopenharmony_ci        __u64 branchInstructionsCount = 0;
44148f512ceSopenharmony_ci        bool other = FindPerCoreEventCount(summary, branchInstructionsCount, otherScale);
44248f512ceSopenharmony_ci        if ((other || (IsMonitoredAtAllTime(otherScale) && IsMonitoredAtAllTime(scale))) &&
44348f512ceSopenharmony_ci            branchInstructionsCount != 0) {
44448f512ceSopenharmony_ci            comment += (static_cast<double>(summary.eventCount) / branchInstructionsCount) * ONE_HUNDRED;
44548f512ceSopenharmony_ci            return "hw-branch-misses";
44648f512ceSopenharmony_ci        }
44748f512ceSopenharmony_ci    }
44848f512ceSopenharmony_ci    return HandleOtherConfig(comment, summary, running_time_in_sec, scale, findRunningTime);
44948f512ceSopenharmony_ci}
45048f512ceSopenharmony_ci
45148f512ceSopenharmony_cistd::string SubCommandStat::HandleOtherConfig(double &comment, PerfEvents::Summary &summary, double running_time_in_sec,
45248f512ceSopenharmony_ci                                              double scale, bool findRunningTime)
45348f512ceSopenharmony_ci{
45448f512ceSopenharmony_ci    comment = 0;
45548f512ceSopenharmony_ci    if (findRunningTime) {
45648f512ceSopenharmony_ci        double rate = 0;
45748f512ceSopenharmony_ci        if (scale != 0) {
45848f512ceSopenharmony_ci            rate = summary.eventCount / (running_time_in_sec / scale);
45948f512ceSopenharmony_ci        }
46048f512ceSopenharmony_ci        comment += rate;
46148f512ceSopenharmony_ci    }
46248f512ceSopenharmony_ci    return "";
46348f512ceSopenharmony_ci}
46448f512ceSopenharmony_ci
46548f512ceSopenharmony_cibool SubCommandStat::IsMonitoredAtAllTime(const double &scale)
46648f512ceSopenharmony_ci{
46748f512ceSopenharmony_ci    constexpr double SCALE_ERROR_LIMIT = 1e-5;
46848f512ceSopenharmony_ci    return (fabs(scale - 1.0) < SCALE_ERROR_LIMIT);
46948f512ceSopenharmony_ci}
47048f512ceSopenharmony_ci
47148f512ceSopenharmony_civoid SubCommandStat::GetComments(const std::map<std::string, std::unique_ptr<PerfEvents::CountEvent>> &countEvents,
47248f512ceSopenharmony_ci    std::map<std::string, std::string> &comments)
47348f512ceSopenharmony_ci{
47448f512ceSopenharmony_ci    double running_time_in_sec = 0;
47548f512ceSopenharmony_ci    __u64 group_id = 0;
47648f512ceSopenharmony_ci    double main_scale = 1.0;
47748f512ceSopenharmony_ci    bool findRunningTime = FindRunningTime(countEvents, running_time_in_sec, group_id, main_scale);
47848f512ceSopenharmony_ci    for (auto it = countEvents.begin(); it != countEvents.end(); it++) {
47948f512ceSopenharmony_ci        std::string configName = it->first;
48048f512ceSopenharmony_ci        std::string commentConfigName = GetCommentConfigName(it->second, "sw-cpu-clock");
48148f512ceSopenharmony_ci        if (configName == commentConfigName) {
48248f512ceSopenharmony_ci            comments[configName] = "";
48348f512ceSopenharmony_ci            continue;
48448f512ceSopenharmony_ci        }
48548f512ceSopenharmony_ci        double scale = 1.0;
48648f512ceSopenharmony_ci        if (it->second->timeRunning < it->second->timeEnabled && it->second->timeRunning != 0) {
48748f512ceSopenharmony_ci            scale = static_cast<double>(it->second->timeEnabled) / it->second->timeRunning;
48848f512ceSopenharmony_ci        }
48948f512ceSopenharmony_ci        commentConfigName = GetCommentConfigName(it->second, "sw-task-clock");
49048f512ceSopenharmony_ci        if (configName == commentConfigName) {
49148f512ceSopenharmony_ci            double usedCpus = it->second->usedCpus * scale;
49248f512ceSopenharmony_ci            comments[configName] = StringPrintf("%lf cpus used", usedCpus);
49348f512ceSopenharmony_ci            continue;
49448f512ceSopenharmony_ci        }
49548f512ceSopenharmony_ci        commentConfigName = GetCommentConfigName(it->second, "hw-cpu-cycles");
49648f512ceSopenharmony_ci        if (configName == commentConfigName) {
49748f512ceSopenharmony_ci            if (findRunningTime &&
49848f512ceSopenharmony_ci                ((group_id == it->second->id) ||
49948f512ceSopenharmony_ci                 (IsMonitoredAtAllTime(main_scale) && IsMonitoredAtAllTime(scale)))) {
50048f512ceSopenharmony_ci                double hz = 0;
50148f512ceSopenharmony_ci                if (abs(running_time_in_sec) > ALMOST_ZERO) {
50248f512ceSopenharmony_ci                    hz = it->second->eventCount / (running_time_in_sec / scale);
50348f512ceSopenharmony_ci                }
50448f512ceSopenharmony_ci                comments[configName] = StringPrintf("%lf GHz", hz / 1e9);
50548f512ceSopenharmony_ci            } else {
50648f512ceSopenharmony_ci                comments[configName] = "";
50748f512ceSopenharmony_ci            }
50848f512ceSopenharmony_ci            continue;
50948f512ceSopenharmony_ci        }
51048f512ceSopenharmony_ci        commentConfigName = GetCommentConfigName(it->second, "hw-instructions");
51148f512ceSopenharmony_ci        if (configName == commentConfigName && it->second->eventCount != 0) {
51248f512ceSopenharmony_ci            std::string cpuSyclesName = GetCommentConfigName(it->second, "hw-cpu-cycles");
51348f512ceSopenharmony_ci            double otherScale = 1.0;
51448f512ceSopenharmony_ci            __u64 cpuCyclesCount = 0;
51548f512ceSopenharmony_ci            bool other = FindEventCount(countEvents, cpuSyclesName, it->second->id, cpuCyclesCount,
51648f512ceSopenharmony_ci                                        otherScale);
51748f512ceSopenharmony_ci            if (other || (IsMonitoredAtAllTime(otherScale) && IsMonitoredAtAllTime(scale))) {
51848f512ceSopenharmony_ci                double cpi = static_cast<double>(cpuCyclesCount) / it->second->eventCount;
51948f512ceSopenharmony_ci                comments[configName] = StringPrintf("%lf cycles per instruction", cpi);
52048f512ceSopenharmony_ci                continue;
52148f512ceSopenharmony_ci            }
52248f512ceSopenharmony_ci        }
52348f512ceSopenharmony_ci        commentConfigName = GetCommentConfigName(it->second, "hw-branch-misses");
52448f512ceSopenharmony_ci        if (configName == commentConfigName) {
52548f512ceSopenharmony_ci            std::string branchInsName = GetCommentConfigName(it->second, "hw-branch-instructions");
52648f512ceSopenharmony_ci            double otherScale = 1.0;
52748f512ceSopenharmony_ci            __u64 branchInstructionsCount = 0;
52848f512ceSopenharmony_ci            bool other = FindEventCount(countEvents, branchInsName, it->second->id,
52948f512ceSopenharmony_ci                                        branchInstructionsCount, otherScale);
53048f512ceSopenharmony_ci            if ((other || (IsMonitoredAtAllTime(otherScale) && IsMonitoredAtAllTime(scale))) &&
53148f512ceSopenharmony_ci                branchInstructionsCount != 0) {
53248f512ceSopenharmony_ci                double miss_rate =
53348f512ceSopenharmony_ci                    static_cast<double>(it->second->eventCount) / branchInstructionsCount;
53448f512ceSopenharmony_ci                comments[configName] = StringPrintf("%lf miss rate", miss_rate * ONE_HUNDRED);
53548f512ceSopenharmony_ci                continue;
53648f512ceSopenharmony_ci            }
53748f512ceSopenharmony_ci        }
53848f512ceSopenharmony_ci        if (findRunningTime && ((group_id == it->second->id) || (IsMonitoredAtAllTime(main_scale) &&
53948f512ceSopenharmony_ci                                                                 IsMonitoredAtAllTime(scale)))) {
54048f512ceSopenharmony_ci            double rate = it->second->eventCount / (running_time_in_sec / scale);
54148f512ceSopenharmony_ci            if (rate > 1e9) {
54248f512ceSopenharmony_ci                comments[configName] = StringPrintf("%.3lf G/sec", rate / 1e9);
54348f512ceSopenharmony_ci                continue;
54448f512ceSopenharmony_ci            }
54548f512ceSopenharmony_ci            if (rate > 1e6) {
54648f512ceSopenharmony_ci                comments[configName] = StringPrintf("%.3lf M/sec", rate / 1e6);
54748f512ceSopenharmony_ci                continue;
54848f512ceSopenharmony_ci            }
54948f512ceSopenharmony_ci            if (rate > 1e3) {
55048f512ceSopenharmony_ci                comments[configName] = StringPrintf("%.3lf K/sec", rate / 1e3);
55148f512ceSopenharmony_ci                continue;
55248f512ceSopenharmony_ci            }
55348f512ceSopenharmony_ci            comments[configName] = StringPrintf("%.3lf /sec", rate);
55448f512ceSopenharmony_ci        } else {
55548f512ceSopenharmony_ci            comments[configName] = "";
55648f512ceSopenharmony_ci        }
55748f512ceSopenharmony_ci    }
55848f512ceSopenharmony_ci}
55948f512ceSopenharmony_ci
56048f512ceSopenharmony_cibool SubCommandStat::FindRunningTime(
56148f512ceSopenharmony_ci    const std::map<std::string, std::unique_ptr<PerfEvents::CountEvent>> &countEvents,
56248f512ceSopenharmony_ci    double &running_time_in_sec, __u64 &group_id, double &main_scale)
56348f512ceSopenharmony_ci{
56448f512ceSopenharmony_ci    for (auto it = countEvents.begin(); it != countEvents.end(); it++) {
56548f512ceSopenharmony_ci        if ((it->first == "sw-task-clock" || it->first == "sw-task-clock:u" ||
56648f512ceSopenharmony_ci             it->first == "sw-task-clock:k" || it->first == "sw-cpu-clock" ||
56748f512ceSopenharmony_ci             it->first == "sw-cpu-clock:u" || it->first == "sw-cpu-clock:k") &&
56848f512ceSopenharmony_ci            it->second->eventCount != 0u) {
56948f512ceSopenharmony_ci            group_id = it->second->id;
57048f512ceSopenharmony_ci            running_time_in_sec = it->second->eventCount / 1e9;
57148f512ceSopenharmony_ci            if (it->second->timeRunning < it->second->timeEnabled &&
57248f512ceSopenharmony_ci                it->second->timeRunning != 0) {
57348f512ceSopenharmony_ci                main_scale =
57448f512ceSopenharmony_ci                    static_cast<double>(it->second->timeEnabled) / it->second->timeRunning;
57548f512ceSopenharmony_ci            }
57648f512ceSopenharmony_ci            return true;
57748f512ceSopenharmony_ci        }
57848f512ceSopenharmony_ci    }
57948f512ceSopenharmony_ci    return false;
58048f512ceSopenharmony_ci}
58148f512ceSopenharmony_ci
58248f512ceSopenharmony_cibool SubCommandStat::FindPercoreRunningTime(PerfEvents::Summary &summary, double &running_time_int_sec,
58348f512ceSopenharmony_ci                                            double &main_scale)
58448f512ceSopenharmony_ci{
58548f512ceSopenharmony_ci    CHECK_TRUE(summary.eventCount == 0, false, 0, "");
58648f512ceSopenharmony_ci    running_time_int_sec = summary.eventCount / 1e9;
58748f512ceSopenharmony_ci    if (summary.timeRunning < summary.timeEnabled && summary.timeRunning != 0) {
58848f512ceSopenharmony_ci        main_scale = static_cast<double>(summary.timeEnabled) / summary.timeRunning;
58948f512ceSopenharmony_ci    }
59048f512ceSopenharmony_ci    return true;
59148f512ceSopenharmony_ci}
59248f512ceSopenharmony_ci
59348f512ceSopenharmony_cibool SubCommandStat::CheckOptionPidAndApp(std::vector<pid_t> pids)
59448f512ceSopenharmony_ci{
59548f512ceSopenharmony_ci    if (!CheckOptionPid(pids)) {
59648f512ceSopenharmony_ci        printf("Problems finding threads of monitor\n\n");
59748f512ceSopenharmony_ci        printf("Usage: perf stat [<options>] [<command>]\n\n");
59848f512ceSopenharmony_ci        printf("-p <pid>        stat events on existing process id\n");
59948f512ceSopenharmony_ci        printf("-t <tid>        stat events on existing thread id\n");
60048f512ceSopenharmony_ci        return false;
60148f512ceSopenharmony_ci    }
60248f512ceSopenharmony_ci    return true;
60348f512ceSopenharmony_ci}
60448f512ceSopenharmony_ci
60548f512ceSopenharmony_cibool SubCommandStat::CheckOptionPid(std::vector<pid_t> pids)
60648f512ceSopenharmony_ci{
60748f512ceSopenharmony_ci    if (pids.empty()) {
60848f512ceSopenharmony_ci        return true;
60948f512ceSopenharmony_ci    }
61048f512ceSopenharmony_ci
61148f512ceSopenharmony_ci    for (auto pid : pids) {
61248f512ceSopenharmony_ci        if (!IsDir("/proc/" + std::to_string(pid))) {
61348f512ceSopenharmony_ci            printf("not exit pid %d\n", pid);
61448f512ceSopenharmony_ci            return false;
61548f512ceSopenharmony_ci        }
61648f512ceSopenharmony_ci    }
61748f512ceSopenharmony_ci    return true;
61848f512ceSopenharmony_ci}
61948f512ceSopenharmony_ci
62048f512ceSopenharmony_civoid SubCommandStat::SetPerfEvent()
62148f512ceSopenharmony_ci{
62248f512ceSopenharmony_ci    SetReportFlags(perCpus_, perThreads_);
62348f512ceSopenharmony_ci    perfEvents_.SetSystemTarget(targetSystemWide_);
62448f512ceSopenharmony_ci    perfEvents_.SetTimeOut(timeStopSec_);
62548f512ceSopenharmony_ci    perfEvents_.SetTimeReport(timeReportMs_);
62648f512ceSopenharmony_ci    perfEvents_.SetPerCpu(perCpus_);
62748f512ceSopenharmony_ci    perfEvents_.SetPerThread(perThreads_);
62848f512ceSopenharmony_ci    perfEvents_.SetVerboseReport(verboseReport_);
62948f512ceSopenharmony_ci    perfEvents_.SetInherit(!noCreateNew_);
63048f512ceSopenharmony_ci    perfEvents_.SetTrackedCommand(trackedCommand_);
63148f512ceSopenharmony_ci    // set report handle
63248f512ceSopenharmony_ci    perfEvents_.SetStatCallBack(Report);
63348f512ceSopenharmony_ci}
63448f512ceSopenharmony_ci
63548f512ceSopenharmony_cibool SubCommandStat::OnSubCommand(std::vector<std::string> &args)
63648f512ceSopenharmony_ci{
63748f512ceSopenharmony_ci    CHECK_TRUE(HelpOption(), true, 0, "");
63848f512ceSopenharmony_ci    if (!CheckRestartOption(appPackage_, targetSystemWide_, restart_, selectPids_)) {
63948f512ceSopenharmony_ci        return false;
64048f512ceSopenharmony_ci    }
64148f512ceSopenharmony_ci    // check option
64248f512ceSopenharmony_ci    if (!CheckSelectCpuPidOption()) {
64348f512ceSopenharmony_ci        return false;
64448f512ceSopenharmony_ci    }
64548f512ceSopenharmony_ci    if (!CheckOptions(selectPids_)) {
64648f512ceSopenharmony_ci        HLOGV("CheckOptions() failed");
64748f512ceSopenharmony_ci        return false;
64848f512ceSopenharmony_ci    }
64948f512ceSopenharmony_ci    if (!CheckAppIsRunning(selectPids_, appPackage_, checkAppMs_)) {
65048f512ceSopenharmony_ci        HLOGV("CheckAppIsRunning() failed");
65148f512ceSopenharmony_ci        return false;
65248f512ceSopenharmony_ci    }
65348f512ceSopenharmony_ci
65448f512ceSopenharmony_ci    perfEvents_.SetCpu(selectCpus_);
65548f512ceSopenharmony_ci    std::vector<pid_t> pids;
65648f512ceSopenharmony_ci    for (auto selectPid : selectPids_) {
65748f512ceSopenharmony_ci        HLOGD("[OnSubCommand] selectPid %d\n", selectPid);
65848f512ceSopenharmony_ci        std::vector<pid_t> subTids = GetSubthreadIDs(selectPid, thread_map_);
65948f512ceSopenharmony_ci        if (!subTids.empty()) {
66048f512ceSopenharmony_ci            pids.insert(pids.end(), subTids.begin(), subTids.end());
66148f512ceSopenharmony_ci        } else {
66248f512ceSopenharmony_ci            HLOGD("[OnSubCommand] subTids empty for %d\n", selectPid);
66348f512ceSopenharmony_ci        }
66448f512ceSopenharmony_ci    }
66548f512ceSopenharmony_ci    pids.insert(pids.end(), selectTids_.begin(), selectTids_.end());
66648f512ceSopenharmony_ci    perfEvents_.SetPid(pids);
66748f512ceSopenharmony_ci    if (!CheckOptionPidAndApp(pids)) {
66848f512ceSopenharmony_ci        HLOGV("CheckOptionPidAndApp() failed");
66948f512ceSopenharmony_ci        return false;
67048f512ceSopenharmony_ci    }
67148f512ceSopenharmony_ci    SetPerfEvent();
67248f512ceSopenharmony_ci    if (!PrepairEvents()) {
67348f512ceSopenharmony_ci        HLOGV("PrepairEvents() failed");
67448f512ceSopenharmony_ci        return false;
67548f512ceSopenharmony_ci    }
67648f512ceSopenharmony_ci
67748f512ceSopenharmony_ci    // preapare fd
67848f512ceSopenharmony_ci    perfEvents_.PrepareTracking();
67948f512ceSopenharmony_ci
68048f512ceSopenharmony_ci    // start tracking
68148f512ceSopenharmony_ci    perfEvents_.StartTracking();
68248f512ceSopenharmony_ci
68348f512ceSopenharmony_ci    return true;
68448f512ceSopenharmony_ci}
68548f512ceSopenharmony_ci
68648f512ceSopenharmony_cibool RegisterSubCommandStat()
68748f512ceSopenharmony_ci{
68848f512ceSopenharmony_ci    return SubCommand::RegisterSubCommand("stat", std::make_unique<SubCommandStat>());
68948f512ceSopenharmony_ci}
69048f512ceSopenharmony_ci
69148f512ceSopenharmony_cibool SubCommandStat::PrepairEvents()
69248f512ceSopenharmony_ci{
69348f512ceSopenharmony_ci    if (selectEvents_.empty() && selectGroups_.empty()) {
69448f512ceSopenharmony_ci        perfEvents_.AddDefaultEvent(PERF_TYPE_HARDWARE);
69548f512ceSopenharmony_ci        perfEvents_.AddDefaultEvent(PERF_TYPE_SOFTWARE);
69648f512ceSopenharmony_ci    } else {
69748f512ceSopenharmony_ci        for (auto events : selectEvents_) {
69848f512ceSopenharmony_ci            if (!perfEvents_.AddEvents(events)) {
69948f512ceSopenharmony_ci                HLOGV("add events failed");
70048f512ceSopenharmony_ci                return false;
70148f512ceSopenharmony_ci            }
70248f512ceSopenharmony_ci        }
70348f512ceSopenharmony_ci        for (auto events : selectGroups_) {
70448f512ceSopenharmony_ci            if (!perfEvents_.AddEvents(events, true)) {
70548f512ceSopenharmony_ci                HLOGV("add groups failed");
70648f512ceSopenharmony_ci                return false;
70748f512ceSopenharmony_ci            }
70848f512ceSopenharmony_ci        }
70948f512ceSopenharmony_ci    }
71048f512ceSopenharmony_ci    return true;
71148f512ceSopenharmony_ci}
71248f512ceSopenharmony_ci
71348f512ceSopenharmony_cibool SubCommandStat::CheckSelectCpuPidOption()
71448f512ceSopenharmony_ci{
71548f512ceSopenharmony_ci    if (!selectCpus_.empty()) {
71648f512ceSopenharmony_ci        // the only value is not -1
71748f512ceSopenharmony_ci        if (!(selectCpus_.size() == 1 && selectCpus_.front() == -1)) {
71848f512ceSopenharmony_ci            int maxCpuid = sysconf(_SC_NPROCESSORS_CONF) - 1;
71948f512ceSopenharmony_ci            for (auto cpu : selectCpus_) {
72048f512ceSopenharmony_ci                if (cpu < 0 || cpu > maxCpuid) {
72148f512ceSopenharmony_ci                    printf("Invalid -c value '%d', the CPU ID should be in 0~%d \n", cpu, maxCpuid);
72248f512ceSopenharmony_ci                    return false;
72348f512ceSopenharmony_ci                }
72448f512ceSopenharmony_ci            }
72548f512ceSopenharmony_ci        }
72648f512ceSopenharmony_ci    } else {
72748f512ceSopenharmony_ci        // the cpu default -1
72848f512ceSopenharmony_ci        if (!targetSystemWide_) {
72948f512ceSopenharmony_ci            selectCpus_.push_back(-1);
73048f512ceSopenharmony_ci        }
73148f512ceSopenharmony_ci    }
73248f512ceSopenharmony_ci
73348f512ceSopenharmony_ci    if (!selectPids_.empty()) {
73448f512ceSopenharmony_ci        for (auto pid : selectPids_) {
73548f512ceSopenharmony_ci            if (pid <= 0) {
73648f512ceSopenharmony_ci                printf("Invalid -p value '%d', the pid should be larger than 0\n", pid);
73748f512ceSopenharmony_ci                return false;
73848f512ceSopenharmony_ci            }
73948f512ceSopenharmony_ci        }
74048f512ceSopenharmony_ci    }
74148f512ceSopenharmony_ci    if (!selectTids_.empty()) {
74248f512ceSopenharmony_ci        for (auto tid : selectTids_) {
74348f512ceSopenharmony_ci            if (tid <= 0) {
74448f512ceSopenharmony_ci                printf("Invalid -t value '%d', the tid should be larger than 0\n", tid);
74548f512ceSopenharmony_ci                return false;
74648f512ceSopenharmony_ci            }
74748f512ceSopenharmony_ci        }
74848f512ceSopenharmony_ci    }
74948f512ceSopenharmony_ci    return true;
75048f512ceSopenharmony_ci}
75148f512ceSopenharmony_ci
75248f512ceSopenharmony_cibool SubCommandStat::CheckOptions(const std::vector<pid_t> &pids)
75348f512ceSopenharmony_ci{
75448f512ceSopenharmony_ci    if (targetSystemWide_) {
75548f512ceSopenharmony_ci        if (!pids.empty() || !selectTids_.empty()) {
75648f512ceSopenharmony_ci            printf("You cannot specify -a and -t/-p at the same time\n");
75748f512ceSopenharmony_ci            return false;
75848f512ceSopenharmony_ci        }
75948f512ceSopenharmony_ci        if (!appPackage_.empty()) {
76048f512ceSopenharmony_ci            printf("You cannot specify -a and --app at the same time\n");
76148f512ceSopenharmony_ci            return false;
76248f512ceSopenharmony_ci        }
76348f512ceSopenharmony_ci    }
76448f512ceSopenharmony_ci    if (!appPackage_.empty() && (!pids.empty() || !selectTids_.empty())) {
76548f512ceSopenharmony_ci        printf("You cannot specify --app and -t/-p at the same time\n");
76648f512ceSopenharmony_ci        return false;
76748f512ceSopenharmony_ci    }
76848f512ceSopenharmony_ci    if (!targetSystemWide_ && trackedCommand_.empty() && pids.empty() && appPackage_.empty()
76948f512ceSopenharmony_ci        && selectTids_.empty()) {
77048f512ceSopenharmony_ci        printf("You need to set the -p option or --app option.\n");
77148f512ceSopenharmony_ci        return false;
77248f512ceSopenharmony_ci    }
77348f512ceSopenharmony_ci    if (targetSystemWide_ && !trackedCommand_.empty()) {
77448f512ceSopenharmony_ci        printf("You cannot specify -a and a cmd at the same time\n");
77548f512ceSopenharmony_ci        return false;
77648f512ceSopenharmony_ci    }
77748f512ceSopenharmony_ci    if (!trackedCommand_.empty()) {
77848f512ceSopenharmony_ci        if (!pids.empty() || !selectTids_.empty()) {
77948f512ceSopenharmony_ci            printf("You cannot specify a cmd and -t/-p at the same time\n");
78048f512ceSopenharmony_ci            return false;
78148f512ceSopenharmony_ci        }
78248f512ceSopenharmony_ci        if (!appPackage_.empty()) {
78348f512ceSopenharmony_ci            printf("You cannot specify a cmd and --app at the same time\n");
78448f512ceSopenharmony_ci            return false;
78548f512ceSopenharmony_ci        }
78648f512ceSopenharmony_ci        if (!IsRoot()) {
78748f512ceSopenharmony_ci            printf("%s options needs root privilege, please check usage\n",
78848f512ceSopenharmony_ci                   VectorToString(trackedCommand_).c_str());
78948f512ceSopenharmony_ci            return false;
79048f512ceSopenharmony_ci        }
79148f512ceSopenharmony_ci    }
79248f512ceSopenharmony_ci    if (checkAppMs_ < MIN_CHECK_APP_MS || checkAppMs_ > MAX_CHECK_APP_MS) {
79348f512ceSopenharmony_ci        printf("Invalid --chkms value '%d', the milliseconds should be in %d~%d \n", checkAppMs_,
79448f512ceSopenharmony_ci               MIN_CHECK_APP_MS, MAX_CHECK_APP_MS);
79548f512ceSopenharmony_ci        return false;
79648f512ceSopenharmony_ci    }
79748f512ceSopenharmony_ci    if (timeStopSec_ < 0) {
79848f512ceSopenharmony_ci        printf("monitoring duration should be positive but %f is given\n", timeStopSec_);
79948f512ceSopenharmony_ci        return false;
80048f512ceSopenharmony_ci    }
80148f512ceSopenharmony_ci    if (timeReportMs_ < 0) {
80248f512ceSopenharmony_ci        printf("print interval should be non-negative but %d is given\n", timeReportMs_);
80348f512ceSopenharmony_ci        return false;
80448f512ceSopenharmony_ci    }
80548f512ceSopenharmony_ci    return true;
80648f512ceSopenharmony_ci}
80748f512ceSopenharmony_ci} // namespace HiPerf
80848f512ceSopenharmony_ci} // namespace Developtools
80948f512ceSopenharmony_ci} // namespace OHOS
810