summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYabin Cui <yabinc@google.com>2020-04-16 18:22:08 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2020-04-16 18:22:08 +0000
commit81fba85a4344bdca1e016a58fe4c0ba38693a8ce (patch)
treebe1212193e816435ef3db3bf4261a583919c1043
parent7681d5f0f8fb4e5c3ad8ad74bd9b917cdc5a52cc (diff)
parentb7241fe18c6fc0dcb9aabff61b7329ad4b12c478 (diff)
downloadextras-81fba85a4344bdca1e016a58fe4c0ba38693a8ce.tar.gz
Merge "simpleperf: support multiple record files in pprof_proto_generator.py."
-rwxr-xr-xsimpleperf/scripts/pprof_proto_generator.py40
-rwxr-xr-xsimpleperf/scripts/test.py21
2 files changed, 40 insertions, 21 deletions
diff --git a/simpleperf/scripts/pprof_proto_generator.py b/simpleperf/scripts/pprof_proto_generator.py
index 2b8b8e24..045ecb3b 100755
--- a/simpleperf/scripts/pprof_proto_generator.py
+++ b/simpleperf/scripts/pprof_proto_generator.py
@@ -244,20 +244,11 @@ class PprofProfileGenerator(object):
def __init__(self, config):
self.config = config
- self.lib = ReportLib()
+ self.lib = None
config['binary_cache_dir'] = 'binary_cache'
if not os.path.isdir(config['binary_cache_dir']):
config['binary_cache_dir'] = None
- else:
- self.lib.SetSymfs(config['binary_cache_dir'])
- if config.get('perf_data_path'):
- self.lib.SetRecordFile(config['perf_data_path'])
- kallsyms = 'binary_cache/kallsyms'
- if os.path.isfile(kallsyms):
- self.lib.SetKallsymsFile(kallsyms)
- if config.get('show_art_frames'):
- self.lib.ShowArtFrames()
self.comm_filter = set(config['comm_filters']) if config.get('comm_filters') else None
if config.get('pid_filters'):
self.pid_filter = {int(x) for x in config['pid_filters']}
@@ -286,12 +277,25 @@ class PprofProfileGenerator(object):
self.binary_map = {}
self.read_elf = ReadElf(self.config['ndk_path'])
- def gen(self):
- # 1. Process all samples in perf.data, aggregate samples.
+ def load_record_file(self, record_file):
+ self.lib = ReportLib()
+ self.lib.SetRecordFile(record_file)
+
+ if self.config['binary_cache_dir']:
+ self.lib.SetSymfs(self.config['binary_cache_dir'])
+ kallsyms = os.path.join(self.config['binary_cache_dir'], 'kallsyms')
+ if os.path.isfile(kallsyms):
+ self.lib.SetKallsymsFile(kallsyms)
+
+ if self.config.get('show_art_frames'):
+ self.lib.ShowArtFrames()
+
+ # Process all samples in perf.data, aggregate samples.
while True:
report_sample = self.lib.GetNextSample()
if report_sample is None:
self.lib.Close()
+ self.lib = None
break
event = self.lib.GetEventOfCurrentSample()
symbol = self.lib.GetSymbolOfCurrentSample()
@@ -315,10 +319,11 @@ class PprofProfileGenerator(object):
if sample.location_ids:
self.add_sample(sample)
- # 2. Generate line info for locations and functions.
+ def gen(self):
+ # 1. Generate line info for locations and functions.
self.gen_source_lines()
- # 3. Produce samples/locations/functions in profile
+ # 2. Produce samples/locations/functions in profile.
for sample in self.sample_list:
self.gen_profile_sample(sample)
for mapping in self.mapping_list:
@@ -591,8 +596,8 @@ class PprofProfileGenerator(object):
def main():
parser = argparse.ArgumentParser(description='Generate pprof profile data in pprof.profile.')
parser.add_argument('--show', nargs='?', action='append', help='print existing pprof.profile.')
- parser.add_argument('-i', '--perf_data_path', default='perf.data', help="""
- The path of profiling data.""")
+ parser.add_argument('-i', '--record_file', nargs='+', default=['perf.data'], help="""
+ Set profiling data file to report. Default is perf.data""")
parser.add_argument('-o', '--output_file', default='pprof.profile', help="""
The path of generated pprof profile data.""")
parser.add_argument('--comm', nargs='+', action='append', help="""
@@ -618,7 +623,6 @@ def main():
return
config = {}
- config['perf_data_path'] = args.perf_data_path
config['output_file'] = args.output_file
config['comm_filters'] = flatten_arg_list(args.comm)
config['pid_filters'] = flatten_arg_list(args.pid)
@@ -628,6 +632,8 @@ def main():
config['show_art_frames'] = args.show_art_frames
config['max_chain_length'] = args.max_chain_length
generator = PprofProfileGenerator(config)
+ for record_file in args.record_file:
+ generator.load_record_file(record_file)
profile = generator.gen()
store_pprof_profile(config['output_file'], profile)
diff --git a/simpleperf/scripts/test.py b/simpleperf/scripts/test.py
index b3e9f186..43966f0a 100755
--- a/simpleperf/scripts/test.py
+++ b/simpleperf/scripts/test.py
@@ -1582,6 +1582,12 @@ class TestPprofProtoGenerator(TestBase):
self.run_cmd(['pprof_proto_generator.py', '-i', testdata_path] + options)
return self.run_cmd(['pprof_proto_generator.py', '--show'], return_output=True)
+ def generate_profile(self, options, testdata_files):
+ testdata_paths = [TEST_HELPER.testdata_path(f) for f in testdata_files]
+ options = options or []
+ self.run_cmd(['pprof_proto_generator.py', '-i'] + testdata_paths + options)
+ return load_pprof_profile('pprof.profile')
+
def test_show_art_frames(self):
art_frame_str = 'art::interpreter::DoCall'
# By default, don't show art frames.
@@ -1632,16 +1638,23 @@ class TestPprofProtoGenerator(TestBase):
""" Test if the address of a location is within the memory range of the corresponding
mapping.
"""
- self.run_cmd(['pprof_proto_generator.py', '-i',
- TEST_HELPER.testdata_path('perf_with_interpreter_frames.data')])
-
- profile = load_pprof_profile('pprof.profile')
+ profile = self.generate_profile(None, ['perf_with_interpreter_frames.data'])
# pylint: disable=no-member
for location in profile.location:
mapping = profile.mapping[location.mapping_id - 1]
self.assertLessEqual(mapping.memory_start, location.address)
self.assertGreaterEqual(mapping.memory_limit, location.address)
+ def test_multiple_perf_data(self):
+ """ Test reporting multiple recording file. """
+ profile1 = self.generate_profile(None, ['aggregatable_perf1.data'])
+ profile2 = self.generate_profile(None, ['aggregatable_perf2.data'])
+ profile_both = self.generate_profile(
+ None, ['aggregatable_perf1.data', 'aggregatable_perf2.data'])
+ # pylint: disable=no-member
+ self.assertGreater(len(profile_both.sample), len(profile1.sample))
+ self.assertGreater(len(profile_both.sample), len(profile2.sample))
+
class TestRecordingRealApps(TestBase):
def setUp(self):