• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <getopt.h>
17 
18 #include "ecmascript/log_wrapper.h"
19 #include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
20 
21 namespace panda::ecmascript::pgo {
22 static const std::string VERSION = "0.0.0.1";
23 static const int MIN_PARAM_COUNT = 3;
24 using ApGenMode = PGOProfilerEncoder::ApGenMode;
25 
26 class Option {
27 public:
28     enum class Mode : uint8_t {
29         VERSION_QUERY,
30         TO_TEXT,
31         MERGE,
32     };
33 
GetProfInPath() const34     std::string GetProfInPath() const
35     {
36         return profInPath_;
37     }
38 
GetProfOutPath() const39     std::string GetProfOutPath() const
40     {
41         return profOutPath_;
42     }
43 
GetHotnessThreshold() const44     uint32_t GetHotnessThreshold() const
45     {
46         return hotnessThreshold_;
47     }
48 
GetMode() const49     Mode GetMode() const
50     {
51         return mode_;
52     }
53 
ParseCommand(const int argc,const char ** argv)54     bool ParseCommand(const int argc, const char **argv)
55     {
56         if (argc <= 1) {
57             return false;
58         }
59 
60         const struct option longOptions[] = {
61             {"text", required_argument, nullptr, 't'},
62             {"hotness-threshold", required_argument, nullptr, 's'},
63             {"merge", no_argument, nullptr, 'm'},
64             {"help", no_argument, nullptr, 'h'},
65             {"version", no_argument, nullptr, 'v'},
66             {nullptr, 0, nullptr, 0},
67         };
68 
69         const char *optstr = "ts:hv";
70         int opt;
71         while ((opt = getopt_long_only(argc, const_cast<char **>(argv), optstr, longOptions, nullptr)) != -1) {
72             switch (opt) {
73                 case 't':
74                     mode_ = Mode::TO_TEXT;
75                     break;
76                 case 's':
77                     if (!base::StringHelper::StrToUInt32(optarg, &hotnessThreshold_)) {
78                         LOG_NO_TAG(ERROR) << "hotness-threshold parse failure";
79                         return false;
80                     }
81                     break;
82                 case 'm':
83                     mode_ = Mode::MERGE;
84                     break;
85                 case 'h':
86                     return false;
87                 case 'v':
88                     mode_ = Mode::VERSION_QUERY;
89                     return true;
90                 default:
91                     LOG_NO_TAG(ERROR) << "Invalid option";
92                     return false;
93             }
94         }
95         if (optind != argc - MIN_PARAM_COUNT + 1) {
96             return false;
97         }
98         profInPath_ = argv[optind];
99         profOutPath_ = argv[optind + 1];
100 
101         return true;
102     }
103 
GetHelper() const104     std::string GetHelper() const
105     {
106         const std::string PROF_DUMP_HELP_HEAD_MSG =
107             "Usage: profdump... SOURCE... DEST... [OPTIONS]\n"
108             "\n"
109             "optional arguments:\n";
110         const std::string PROF_DUMP_HELP_OPTION_MSG =
111             "-t, --text                binary to text.\n"
112             "-s, --hotness-threshold   set minimum number of calls to filter method. default: 2\n"
113             "-m, --merge               merge multi binary ap files into one.\n"
114             "-h, --help                display this help and exit\n"
115             "-v, --version             output version information and exit\n";
116         return PROF_DUMP_HELP_HEAD_MSG + PROF_DUMP_HELP_OPTION_MSG;
117     }
118 
GetVersion() const119     const std::string GetVersion() const
120     {
121         return VERSION;
122     }
123 
124 private:
125     Mode mode_ { Mode::TO_TEXT };
126     uint32_t hotnessThreshold_ { 1 };
127     std::string profInPath_;
128     std::string profOutPath_;
129 };
130 
Main(const int argc,const char ** argv)131 int Main(const int argc, const char **argv)
132 {
133     Option option;
134     if (!option.ParseCommand(argc, argv)) {
135         LOG_NO_TAG(ERROR) << option.GetHelper();
136         return  -1;
137     }
138     switch (option.GetMode()) {
139         case Option::Mode::VERSION_QUERY:
140             LOG_NO_TAG(ERROR) << "Ver: " << VERSION;
141             break;
142         case Option::Mode::TO_TEXT: {
143             if (PGOProfilerManager::GetInstance()->BinaryToText(option.GetProfInPath(),
144                 option.GetProfOutPath(), option.GetHotnessThreshold())) {
145                 LOG_NO_TAG(ERROR) << "profiler dump to text success!";
146             } else {
147                 LOG_NO_TAG(ERROR) << "profiler dump to text failed!";
148             }
149             break;
150         }
151         case Option::Mode::MERGE: {
152             // For CLI tools, do not merge with existed output file
153             if (PGOProfilerManager::MergeApFiles(option.GetProfInPath(), option.GetProfOutPath(),
154                                                  option.GetHotnessThreshold(), ApGenMode::OVERWRITE)) {
155                 LOG_NO_TAG(ERROR) << "profiler merge success!";
156             }
157             break;
158         }
159         default:
160             break;
161     }
162     return 0;
163 }
164 } // namespace panda::ecmascript::pgo
165 
main(int argc,const char ** argv)166 int main(int argc, const char **argv)
167 {
168     return panda::ecmascript::pgo::Main(argc, argv);
169 }
170