1#!/usr/bin/env python 2# -*- coding: utf-8 -*- 3# Copyright (c) 2025 Huawei Device Co., Ltd. 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15 16import os 17import sys 18import time 19import argparse 20from hiperf_utils import PerformanceProfile 21from hiperf_utils import get_arg_list 22from hiperf_utils import dir_check 23from hiperf_utils import get_lib 24from record_control import check_args 25from test_02_recv_binary_cache import GetLibFiles 26 27 28def get_used_binaries(perf_data, report_file, binary_cache, html_template): 29 if binary_cache: 30 get_lib().ReportUnwindJson(perf_data.encode("utf-8"), 31 'json.txt'.encode("utf-8"), 32 binary_cache.encode("utf-8")) 33 else: 34 get_lib().ReportJson(perf_data.encode("utf-8"), 35 'json.txt'.encode("utf-8")) 36 time.sleep(2) 37 with open('json.txt', 'r') as json_file: 38 all_json = json_file.read() 39 template = os.path.join(html_template, './testModule/report.html') 40 with open(template, 'r', encoding='utf-8') as html_file: 41 html_str = html_file.read() 42 with open(report_file, 'w', encoding='utf-8') as report_html_file: 43 report_html_file.write(html_str + all_json + '</script>' 44 ' </body>' 45 ' </html>') 46 dirname, _ = os.path.split(os.path.abspath(sys.argv[0])) 47 abs_path = os.path.join(dirname, report_file) 48 print("save to %s success" % abs_path) 49 os.remove('json.txt') 50 51 52def add_target_argument(parser): 53 target_group = parser.add_argument_group(title='Select profiling target') \ 54 .add_mutually_exclusive_group(required=True) 55 target_group.add_argument('-app', '--package_name', 56 help="""Collect profile info for an OHOS app""") 57 58 target_group.add_argument('-lp', '--local_program', 59 help="""Collect profile info 60 for an local program.""") 61 62 target_group.add_argument('-cmd', 63 help="""Running a command on the OHOS device. 64 like as : -cmd "'ps -ef'". 65 the ps will open as child process of hiperf 66 and sample this process.""") 67 68 target_group.add_argument('-p', '--pid', nargs='*', 69 help="""Limit the process id of the collection 70 target.""") 71 72 target_group.add_argument('-t', '--tid', nargs='*', 73 help="""Limit the thread id of the collection 74 target.""") 75 76 target_group.add_argument('-sw', '--system_wide', action='store_true', 77 help="""Collect system-wide information. 78 This requires CAP_PERFMON (since Linux 5.8) or 79 CAP_SYS_ADMIN capability or a 80 /proc/sys/kernel/perf_event_paranoid 81 value of less than 1.""") 82 83 84def add_record_argument(parser): 85 record_group = parser.add_argument_group('Select recording options') 86 record_group.add_argument('-a', '--ability', 87 help="""Used with -p. Profile the launch time of 88 an ability in an OHOS app. The app will be started or 89 restarted to run the ability. 90 Like : -a .MainAbility """) 91 92 record_group.add_argument('-d', '--record_options', 93 default='-f 1000 -d 10 -s dwarf', 94 help="""Set recording options for `hiperf record` 95 command. Default is "'-f 1000 -d 10 -s dwarf'".""") 96 97 record_group.add_argument('-o', '--output_perf_data', default='perf.data', 98 help='The path to store profiling data. ' 99 'Default is perf.data.') 100 record_group.add_argument('-lib', '--local_lib_dir', type=dir_check, 101 help="""When profiling an OHOS app containing 102 local thelocal libraries are usually stripped and lake 103 of symbols and debug information to provide good 104 profiling result. By using -lib, you tell 105 command_script.py the path storing unstripped local 106 libraries, and script will search all shared libraries 107 with suffix .so in the directory. Then the local 108 libraries will be downloaded on device and collected 109 in build_cache.""") 110 111 112def add_recver_argument(parser): 113 recver_group = parser.add_argument_group('Recver options') 114 115 recver_group.add_argument('-i', '--perf_data', default='perf.data', 116 help=""" The path of profiling data.""") 117 recver_group.add_argument('-l', '--local_library_dir', type=dir_check, nargs='+', 118 help="""Path to find debug version of local shared 119 libraries used in the app.""", action='append') 120 recver_group.add_argument('-c', '--copy_symbol_from_device', default='0', 121 help=""" Copy symbol files from device.""") 122 123 124def add_report_argument(parser): 125 report_group = parser.add_argument_group('Report options') 126 report_group.add_argument('-r', '--report_html', default='hiperf_report.html', 127 help="""the path of the report.""") 128 report_group.add_argument('-m', '--html_template', default='./', 129 help=""" The path of report html template 130 """) 131 report_group.add_argument('-b', '--binary_cache', type=dir_check, default='./testModule/binary_cache', 132 help="""Path to find symbol dir use to 133 do offline unwind stack""") 134 135 136def parser_add_argument(): 137 description = "Collect performance sampling information of" \ 138 " running [command]." 139 parser = argparse.ArgumentParser(description=description) 140 add_target_argument(parser) 141 add_record_argument(parser) 142 143 other_group = parser.add_argument_group('Other options') 144 other_group.add_argument('--not_hdc_root', action='store_true', 145 help="""Force hdc to run in non root mode. """) 146 147 add_recver_argument(parser) 148 add_report_argument(parser) 149 args = parser.parse_args() 150 return args 151 152 153def main(args): 154 check_args(args) 155 profiler = PerformanceProfile(args) 156 profiler.profile() 157 recver = GetLibFiles() 158 library_dirs = get_arg_list(args.local_library_dir) 159 recver.recv_binary_cache(args.perf_data, library_dirs, 160 args.copy_symbol_from_device == '1' or args.copy_symbol_from_device == 'true') 161 get_used_binaries(args.perf_data, args.report_html, args.binary_cache, args.html_template) 162 return True 163 164 165if __name__ == '__main__': 166 main(parser_add_argument()) 167