diff options
author | Yabin Cui <yabinc@google.com> | 2024-02-06 19:34:04 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2024-02-06 19:34:04 +0000 |
commit | 8b9f1bed2387a4032bcdfe8df615c88904d89978 (patch) | |
tree | cb24d6b01fc7d6da50233daad5f2b8761f120096 /simpleperf | |
parent | f45b9c81725ab74d79854b1e6f575f9a21b0d136 (diff) | |
parent | 40a51f76d7d6e315f2c66668e9234fc2faee85c4 (diff) | |
download | extras-8b9f1bed2387a4032bcdfe8df615c88904d89978.tar.gz |
Merge "simpleperf: report_html.py: split disassemble work evenly" into main
Diffstat (limited to 'simpleperf')
-rwxr-xr-x | simpleperf/scripts/report_html.py | 64 | ||||
-rw-r--r-- | simpleperf/scripts/simpleperf_utils.py | 9 |
2 files changed, 48 insertions, 25 deletions
diff --git a/simpleperf/scripts/report_html.py b/simpleperf/scripts/report_html.py index 368bd509..ba143fd0 100755 --- a/simpleperf/scripts/report_html.py +++ b/simpleperf/scripts/report_html.py @@ -801,7 +801,8 @@ class RecordData(object): # Collect needed source code in SourceFileSet. self.source_files.load_source_code(source_dirs) - def add_disassembly(self, filter_lib: Callable[[str], bool], jobs: int): + def add_disassembly(self, filter_lib: Callable[[str], bool], + jobs: int, disassemble_job_size: int): """ Collect disassembly information: 1. Use objdump to collect disassembly for each function in FunctionSet. 2. Set flag to dump addr_hit_map when generating record info. @@ -816,6 +817,7 @@ class RecordData(object): with ThreadPoolExecutor(jobs) as executor: futures: List[Future] = [] + all_tasks = [] for lib_id, functions in lib_functions.items(): lib = self.libs.get_lib(lib_id) if not filter_lib(lib.name): @@ -823,33 +825,45 @@ class RecordData(object): dso_info = objdump.get_dso_info(lib.name, lib.build_id) if not dso_info: continue - # If there are not many functions, it's faster to disassemble them one by one. - # Otherwise it's faster to disassemble the whole binary. - if len(functions) < jobs: - for function in functions: - futures.append(executor.submit(self._disassemble_function, objdump, - dso_info, function)) - else: - futures.append(executor.submit(self._disassemble_binary, objdump, dso_info, - functions)) - for future in futures: - future.result() + tasks = self.split_disassembly_jobs(functions, disassemble_job_size) + logging.debug('create %d jobs to disassemble %d functions in %s', + len(tasks), len(functions), lib.name) + for task in tasks: + futures.append(executor.submit( + self._disassemble_functions, objdump, dso_info, task)) + all_tasks.append(task) + + for task, future in zip(all_tasks, futures): + result = future.result() + if result and len(result) == len(task): + for function, disassembly in zip(task, result): + function.disassembly = disassembly.lines + + logging.debug('finished all disassemble jobs') self.gen_addr_hit_map_in_record_info = True - def _disassemble_function(self, objdump: Objdump, dso_info, function: Function): - result = objdump.disassemble_function(dso_info, AddrRange(function.start_addr, - function.addr_len)) - if result: - function.disassembly = result.lines - - def _disassemble_binary(self, objdump: Objdump, dso_info, functions: List[Function]): + def split_disassembly_jobs(self, functions: List[Function], + disassemble_job_size: int) -> List[List[Function]]: + """ Decide how to split the task of dissassembly functions in one library. """ + if not functions: + return [] functions.sort(key=lambda f: f.start_addr) + result = [] + job_start_addr = None + for function in functions: + if (job_start_addr is None or + function.start_addr - job_start_addr > disassemble_job_size): + job_start_addr = function.start_addr + result.append([function]) + else: + result[-1].append(function) + return result + + def _disassemble_functions(self, objdump: Objdump, dso_info, + functions: List[Function]) -> Optional[List[Disassembly]]: addr_ranges = [AddrRange(f.start_addr, f.addr_len) for f in functions] - result = objdump.disassemble_functions(dso_info, addr_ranges) - if result: - for i in range(len(functions)): - functions[i].disassembly = result[i].lines + return objdump.disassemble_functions(dso_info, addr_ranges) def gen_record_info(self) -> Dict[str, Any]: """ Return json data which will be used by report_html.js. """ @@ -1010,6 +1024,8 @@ def get_args() -> argparse.Namespace: parser.add_argument('--add_source_code', action='store_true', help='Add source code.') parser.add_argument('--source_dirs', nargs='+', help='Source code directories.') parser.add_argument('--add_disassembly', action='store_true', help='Add disassembled code.') + parser.add_argument('--disassemble-job-size', type=int, default=1024*1024, + help='address range for one disassemble job') parser.add_argument('--binary_filter', nargs='+', help="""Annotate source code and disassembly only for selected binaries.""") parser.add_argument( @@ -1064,7 +1080,7 @@ def main(): if args.add_source_code: record_data.add_source_code(args.source_dirs, filter_lib, args.jobs) if args.add_disassembly: - record_data.add_disassembly(filter_lib, args.jobs) + record_data.add_disassembly(filter_lib, args.jobs, args.disassemble_job_size) # 3. Generate report html. report_generator = ReportGenerator(args.report_path) diff --git a/simpleperf/scripts/simpleperf_utils.py b/simpleperf/scripts/simpleperf_utils.py index 04939a8d..af4fca1b 100644 --- a/simpleperf/scripts/simpleperf_utils.py +++ b/simpleperf/scripts/simpleperf_utils.py @@ -869,6 +869,8 @@ class Objdump(object): """ Disassemble code for multiple addr ranges in a binary. sorted_addr_ranges should be sorted by addr_range.start. """ + if not sorted_addr_ranges: + return [] real_path, arch = dso_info objdump_path = self.objdump_paths.get(arch) if not objdump_path: @@ -878,7 +880,12 @@ class Objdump(object): self.objdump_paths[arch] = objdump_path # Run objdump. - args = [objdump_path, '-dlC', '--no-show-raw-insn', real_path] + start_addr = sorted_addr_ranges[0].start + stop_addr = max(addr_range.end for addr_range in sorted_addr_ranges) + args = [objdump_path, '-dlC', '--no-show-raw-insn', + '--start-address=0x%x' % start_addr, + '--stop-address=0x%x' % stop_addr, + real_path] if arch == 'arm' and 'llvm-objdump' in objdump_path: args += ['--print-imm-hex'] try: |