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#ifndef SUBCOMMAND_REPORT_H
1748f512ceSopenharmony_ci#define SUBCOMMAND_REPORT_H
1848f512ceSopenharmony_ci
1948f512ceSopenharmony_ci#include <algorithm>
2048f512ceSopenharmony_ci#include <cstdio>
2148f512ceSopenharmony_ci#include <cstdlib>
2248f512ceSopenharmony_ci#include <functional>
2348f512ceSopenharmony_ci#include <map>
2448f512ceSopenharmony_ci#include <optional>
2548f512ceSopenharmony_ci#include <set>
2648f512ceSopenharmony_ci#include <tuple>
2748f512ceSopenharmony_ci#include <linux/perf_event.h>
2848f512ceSopenharmony_ci
2948f512ceSopenharmony_ci#include "perf_file_reader.h"
3048f512ceSopenharmony_ci#if defined(HAVE_PROTOBUF) && HAVE_PROTOBUF
3148f512ceSopenharmony_ci#include "report_protobuf_file.h"
3248f512ceSopenharmony_ci#endif
3348f512ceSopenharmony_ci#include "debug_logger.h"
3448f512ceSopenharmony_ci#include "option.h"
3548f512ceSopenharmony_ci#include "perf_event_record.h"
3648f512ceSopenharmony_ci#include "report.h"
3748f512ceSopenharmony_ci#include "report_json_file.h"
3848f512ceSopenharmony_ci#include "subcommand.h"
3948f512ceSopenharmony_ci#include "symbols_file.h"
4048f512ceSopenharmony_ci#include "utilities.h"
4148f512ceSopenharmony_ci#include "virtual_runtime.h"
4248f512ceSopenharmony_ci
4348f512ceSopenharmony_cinamespace OHOS {
4448f512ceSopenharmony_cinamespace Developtools {
4548f512ceSopenharmony_cinamespace HiPerf {
4648f512ceSopenharmony_ciclass SubCommandReport : public SubCommand {
4748f512ceSopenharmony_cipublic:
4848f512ceSopenharmony_ci    SubCommandReport()
4948f512ceSopenharmony_ci        // clang-format off
5048f512ceSopenharmony_ci        : SubCommand("report", "report sampling information from perf.data format file",
5148f512ceSopenharmony_ci        "Usage: hiperf report [options]\n"
5248f512ceSopenharmony_ci        "       The default options are same as :\n"
5348f512ceSopenharmony_ci        "       -i perf.data --sort comm,pid,tid,dso,func\n"
5448f512ceSopenharmony_ci        "   --symbol-dir <dir>\n"
5548f512ceSopenharmony_ci        "       use symbols path to find symbols.\n"
5648f512ceSopenharmony_ci        "       separate the paths with commas.\n"
5748f512ceSopenharmony_ci        "   --limit-percent <number>\n"
5848f512ceSopenharmony_ci        "       only show heat percent limit content.\n"
5948f512ceSopenharmony_ci        "   -s / --call-stack\n"
6048f512ceSopenharmony_ci        "       show the unwind callstack\n"
6148f512ceSopenharmony_ci        "   --call-stack-limit-percent <number>\n"
6248f512ceSopenharmony_ci        "       only show the callstack heat percent limit content.\n"
6348f512ceSopenharmony_ci        "   --proto\n"
6448f512ceSopenharmony_ci        "       show protobuf content in the save file name.\n"
6548f512ceSopenharmony_ci        "       default file name is perf.data.\n"
6648f512ceSopenharmony_ci        "   --json\n"
6748f512ceSopenharmony_ci        "       report in json format.\n"
6848f512ceSopenharmony_ci        "       default file name is perf.data.\n"
6948f512ceSopenharmony_ci        "   --diff <target file>\n"
7048f512ceSopenharmony_ci        "       show the diff result from -i to -diff .\n"
7148f512ceSopenharmony_ci        "       example: \"report -i a.data --diff b.data\"\n"
7248f512ceSopenharmony_ci        "   --branch\n"
7348f512ceSopenharmony_ci        "       show the branch from address instead of ip address\n"
7448f512ceSopenharmony_ci        "   --<keys> <keyname1>[,keyname2][,...]\n"
7548f512ceSopenharmony_ci        "       select able keys: comms,pids,tids,dsos,funcs,from_dsos,from_funcs\n"
7648f512ceSopenharmony_ci        "           example: --comms hiperf\n"
7748f512ceSopenharmony_ci        "   --sort <key1>[,key2][,...]\n"
7848f512ceSopenharmony_ci        "       Choose some keywords.\n"
7948f512ceSopenharmony_ci        "       These keywords will be used for sorting.\n"
8048f512ceSopenharmony_ci        "       Only selected keywords will appear in the report.\n"
8148f512ceSopenharmony_ci        "\n"
8248f512ceSopenharmony_ci        "           pid             -- process id\n"
8348f512ceSopenharmony_ci        "           tid             -- thread id\n"
8448f512ceSopenharmony_ci        "           comm            -- thread name (can be changed for same thread)\n"
8548f512ceSopenharmony_ci        "           dso             -- like dso name , or elf path\n"
8648f512ceSopenharmony_ci        "           func            -- function name in the symbols\n"
8748f512ceSopenharmony_ci        "\n"
8848f512ceSopenharmony_ci        "       in branch mode:\n"
8948f512ceSopenharmony_ci        "           from_dso        -- branched from dso or elf\n"
9048f512ceSopenharmony_ci        "           from_func       -- branched from function\n"
9148f512ceSopenharmony_ci        "           dso             -- means branched to dso or elf\n"
9248f512ceSopenharmony_ci        "           func            -- means branched to function\n"
9348f512ceSopenharmony_ci        "   -i <filename>\n"
9448f512ceSopenharmony_ci        "           perf data file to report, default is perf.data\n"
9548f512ceSopenharmony_ci        "   -o <filename>\n"
9648f512ceSopenharmony_ci        "           report file name. if empty will use stdout print\n"
9748f512ceSopenharmony_ci        "   --hide_count\n"
9848f512ceSopenharmony_ci        "           will not show count in report\n"
9948f512ceSopenharmony_ci        "   --dumpoptions\n"
10048f512ceSopenharmony_ci        "           Dump command options.\n"
10148f512ceSopenharmony_ci        "\n"
10248f512ceSopenharmony_ci        ), recordFile_ {"perf.data", ""} // default file path is perf.data
10348f512ceSopenharmony_ci    // clang-format on
10448f512ceSopenharmony_ci    {
10548f512ceSopenharmony_ci    }
10648f512ceSopenharmony_ci    bool OnSubCommand(std::vector<std::string> &args) override;
10748f512ceSopenharmony_ci    bool ParseOption(std::vector<std::string> &args) override;
10848f512ceSopenharmony_ci    void DumpOptions(void) const override;
10948f512ceSopenharmony_ci    static bool RegisterSubCommandReport(void);
11048f512ceSopenharmony_ci    bool RecordCallBack(std::unique_ptr<PerfEventRecord> record);
11148f512ceSopenharmony_ci
11248f512ceSopenharmony_ci    ~SubCommandReport();
11348f512ceSopenharmony_ci
11448f512ceSopenharmony_ciprivate:
11548f512ceSopenharmony_ci    void ProcessSample(std::unique_ptr<PerfRecordSample> &);
11648f512ceSopenharmony_ci    void BroadcastSample(std::unique_ptr<PerfRecordSample> &);
11748f512ceSopenharmony_ci
11848f512ceSopenharmony_ci    bool VerifyOption();
11948f512ceSopenharmony_ci    bool VerifyDisplayOption();
12048f512ceSopenharmony_ci
12148f512ceSopenharmony_ci    // load
12248f512ceSopenharmony_ci    bool PrepareOutput();
12348f512ceSopenharmony_ci    bool LoadPerfData();
12448f512ceSopenharmony_ci    void ProcessFeaturesData();
12548f512ceSopenharmony_ci    void LoadEventConfigData();
12648f512ceSopenharmony_ci    void LoadAttrSection();
12748f512ceSopenharmony_ci    void LoadEventDesc();
12848f512ceSopenharmony_ci    void ProcessSymbolsData();
12948f512ceSopenharmony_ci    void LoadPerfDataCompleted();
13048f512ceSopenharmony_ci    void ProcessUniStackTableData();
13148f512ceSopenharmony_ci
13248f512ceSopenharmony_ci    bool OutputReport();
13348f512ceSopenharmony_ci    bool OutputStd();
13448f512ceSopenharmony_ci
13548f512ceSopenharmony_ci    // prefdata
13648f512ceSopenharmony_ci    bool showCallStack_ = false;
13748f512ceSopenharmony_ci    bool diffMode_ = false;
13848f512ceSopenharmony_ci
13948f512ceSopenharmony_ci    // create record file reader pointer
14048f512ceSopenharmony_ci    std::unique_ptr<PerfFileReader> recordFileReader_;
14148f512ceSopenharmony_ci    std::vector<std::string> symbolsPaths_;
14248f512ceSopenharmony_ci
14348f512ceSopenharmony_ci    // report file name , if empty will use stdout
14448f512ceSopenharmony_ci    std::string reportFile_;
14548f512ceSopenharmony_ci
14648f512ceSopenharmony_ci    // for diff report
14748f512ceSopenharmony_ci    enum RecordIndex { FIRST = 0, SECOND = 1, MAX = 2, CURRENT = -1 } index_ = FIRST;
14848f512ceSopenharmony_ci    std::string recordFile_[MAX];
14948f512ceSopenharmony_ci    ReportOption reportOption_;
15048f512ceSopenharmony_ci    Report report_[MAX] = {reportOption_, reportOption_};
15148f512ceSopenharmony_ci    inline Report &GetReport(RecordIndex index = CURRENT, int configId = 0)
15248f512ceSopenharmony_ci    {
15348f512ceSopenharmony_ci        if (index == CURRENT) {
15448f512ceSopenharmony_ci            return report_[index_];
15548f512ceSopenharmony_ci        } else {
15648f512ceSopenharmony_ci            return report_[index];
15748f512ceSopenharmony_ci        }
15848f512ceSopenharmony_ci    }
15948f512ceSopenharmony_ci
16048f512ceSopenharmony_ci    std::vector<std::string> configNames_;
16148f512ceSopenharmony_ci    std::set<uint64_t> cpuOffids_;
16248f512ceSopenharmony_ci
16348f512ceSopenharmony_ci    const std::string cpuOffEventName = "sched:sched_switch";
16448f512ceSopenharmony_ci    bool cpuOffMode_ = false;
16548f512ceSopenharmony_ci    std::map<pid_t, std::unique_ptr<PerfRecordSample>> prevSampleCache_;
16648f512ceSopenharmony_ci    void FlushCacheRecord();
16748f512ceSopenharmony_ci
16848f512ceSopenharmony_ci    // in debug mode we will output some more debug info
16948f512ceSopenharmony_ci    bool debug_ = false;
17048f512ceSopenharmony_ci    bool branch_ = false;
17148f512ceSopenharmony_ci    bool jsonFormat_ = false;
17248f512ceSopenharmony_ci
17348f512ceSopenharmony_ci    FILE *output_ = nullptr;
17448f512ceSopenharmony_ci
17548f512ceSopenharmony_ci    std::unique_ptr<ReportJsonFile> reportJsonFile_ = nullptr;
17648f512ceSopenharmony_ci
17748f512ceSopenharmony_ci    bool protobufFormat_ = false;
17848f512ceSopenharmony_ci#if defined(HAVE_PROTOBUF) && HAVE_PROTOBUF
17948f512ceSopenharmony_ci    std::unique_ptr<ReportProtobufFileWriter> protobufOutputFileWriter_ = nullptr;
18048f512ceSopenharmony_ci    void UpdateReportInfo();
18148f512ceSopenharmony_ci#endif
18248f512ceSopenharmony_ci    friend class SubCommandReportTest;
18348f512ceSopenharmony_ci    FRIEND_TEST(SubCommandReportTest, TestLoadPerfData);
18448f512ceSopenharmony_ci    FRIEND_TEST(SubCommandReportTest, TestOutputReport);
18548f512ceSopenharmony_ci    FRIEND_TEST(SubCommandReportTest, TestOutputStd);
18648f512ceSopenharmony_ci    FRIEND_TEST(SubCommandReportTest, TestVerifyOption);
18748f512ceSopenharmony_ci    FRIEND_TEST(SubCommandReportTest, TestVerifyDisplayOption);
18848f512ceSopenharmony_ci    FRIEND_TEST(SubCommandReportTest, TestPrepareConsole);
18948f512ceSopenharmony_ci    FRIEND_TEST(SubCommandReportTest, TestPrepareConsole);
19048f512ceSopenharmony_ci
19148f512ceSopenharmony_ci    void SetHM();
19248f512ceSopenharmony_ci};
19348f512ceSopenharmony_ci} // namespace HiPerf
19448f512ceSopenharmony_ci} // namespace Developtools
19548f512ceSopenharmony_ci} // namespace OHOS
19648f512ceSopenharmony_ci#endif // SUBCOMMAND_REPORT_H
197