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
23 namespace panda::ecmascript {
24 static const std::string VERSION = "0.0.0.1";
25 static const int MIN_PARAM_COUNT = 3;
26
27 class Option {
28 public:
29 enum class Mode : uint8_t {
30 VERSION_QUERY,
31 TO_BINARY,
32 TO_TEXT,
33 };
34
GetProfInPath() const35 std::string GetProfInPath() const
36 {
37 return profInPath_;
38 }
39
GetProfOutPath() const40 std::string GetProfOutPath() const
41 {
42 return profOutPath_;
43 }
44
GetHotnessThreshold() const45 uint32_t GetHotnessThreshold() const
46 {
47 return hotnessThreshold_;
48 }
49
GetMode() const50 Mode GetMode() const
51 {
52 return mode_;
53 }
54
ParseCommand(const int argc,const char ** argv)55 bool ParseCommand(const int argc, const char **argv)
56 {
57 if (argc <= 1) {
58 return false;
59 }
60
61 const struct option longOptions[] = {
62 {"text", required_argument, nullptr, 't'},
63 {"binary", required_argument, nullptr, 'b'},
64 {"hotness-threshold", required_argument, nullptr, 's'},
65 {"help", no_argument, nullptr, 'h'},
66 {"version", no_argument, nullptr, 'v'},
67 {nullptr, 0, nullptr, 0},
68 };
69
70 const char *optstr = "tbs:hv";
71 int opt;
72 while ((opt = getopt_long_only(argc, const_cast<char **>(argv), optstr, longOptions, nullptr)) != -1) {
73 switch (opt) {
74 case 't':
75 mode_ = Mode::TO_TEXT;
76 break;
77 case 'b':
78 mode_ = Mode::TO_BINARY;
79 break;
80 case 's':
81 if (!base::StringHelper::StrToUInt32(optarg, &hotnessThreshold_)) {
82 LOG_NO_TAG(ERROR) << "hotness-threshold parse failure";
83 return false;
84 }
85 break;
86 case 'h':
87 return false;
88 case 'v':
89 mode_ = Mode::VERSION_QUERY;
90 return true;
91 default:
92 LOG_NO_TAG(ERROR) << "Invalid option";
93 return false;
94 }
95 }
96 if (optind != argc - MIN_PARAM_COUNT + 1) {
97 return false;
98 }
99 profInPath_ = argv[optind];
100 profOutPath_ = argv[optind + 1];
101
102 return true;
103 }
104
GetHelper() const105 std::string GetHelper() const
106 {
107 const std::string PROF_DUMP_HELP_HEAD_MSG =
108 "Usage: profdump... SOURCE... DEST... [OPTIONS]\n"
109 "\n"
110 "optional arguments:\n";
111 const std::string PROF_DUMP_HELP_OPTION_MSG =
112 "-t, --text binary to text.\n"
113 "-b, --binary text to binary.\n"
114 "-s, --hotness-threshold set minimum number of calls to filter method. default: 2\n"
115 "-h, --help display this help and exit\n"
116 "-v, --version output version information and exit\n";
117 return PROF_DUMP_HELP_HEAD_MSG + PROF_DUMP_HELP_OPTION_MSG;
118 }
119
GetVersion() const120 const std::string GetVersion() const
121 {
122 return VERSION;
123 }
124
125 private:
126 Mode mode_ { Mode::TO_TEXT };
127 uint32_t hotnessThreshold_ { 2 };
128 std::string profInPath_;
129 std::string profOutPath_;
130 };
131
Main(const int argc,const char ** argv)132 int Main(const int argc, const char **argv)
133 {
134 Option option;
135 if (!option.ParseCommand(argc, argv)) {
136 LOG_NO_TAG(ERROR) << option.GetHelper();
137 return -1;
138 }
139 switch (option.GetMode()) {
140 case Option::Mode::VERSION_QUERY:
141 LOG_NO_TAG(ERROR) << "Ver: " << VERSION;
142 break;
143 case Option::Mode::TO_TEXT: {
144 if (PGOProfilerManager::GetInstance()->BinaryToText(option.GetProfInPath(),
145 option.GetProfOutPath(), option.GetHotnessThreshold())) {
146 LOG_NO_TAG(ERROR) << "profiler dump to text success!";
147 } else {
148 LOG_NO_TAG(ERROR) << "profiler dump to text failed!";
149 }
150 break;
151 }
152 case Option::Mode::TO_BINARY: {
153 if (PGOProfilerManager::GetInstance()->TextToBinary(option.GetProfInPath(),
154 option.GetProfOutPath(), option.GetHotnessThreshold())) {
155 LOG_NO_TAG(ERROR) << "profiler dump to binary success!";
156 } else {
157 LOG_NO_TAG(ERROR) << "profiler dump to binary failed!";
158 }
159 break;
160 }
161 default:
162 break;
163 }
164 return 0;
165 }
166 } // namespace panda::ecmascript
167
main(int argc,const char ** argv)168 int main(int argc, const char **argv)
169 {
170 return panda::ecmascript::Main(argc, argv);
171 }
172