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