def main(): # Parse arguments passed from command line parser = argparse.ArgumentParser() parser.add_argument( "-a", "--address", help="Address at which trace_processor is being run, e.g. localhost:9001", type=str) parser.add_argument("-f", "--file", help="Absolute path to trace", type=str) args = parser.parse_args() # Pass arguments into api to construct the trace processor and load the trace if args.address == None and args.file == None: raise Exception("You must specify an address or a file path to trace") elif args.address == None: tp = TraceProcessor(file_path=args.file) elif args.file == None: tp = TraceProcessor(uri=args.address) else: tp = TraceProcessor(uri=args.address, file_path=args.file) # Call functions on the loaded trace res_it = tp.query('select * from slice limit 10') for row in res_it: print(row.name) am_metrics = tp.metric(['android_mem']) tp.close()
def test_many_batches(self): # Construct expected results int_values = [100, 200, 300, 400] str_values = ['bar1', 'bar2', 'bar3', 'bar4'] # Create cells batches to populate QueryResult batch_1 = ProtoFactory().CellsBatch() batch_1.cells.extend([ TestQueryResultIterator.CELL_STRING, TestQueryResultIterator.CELL_VARINT, TestQueryResultIterator.CELL_STRING, TestQueryResultIterator.CELL_VARINT ]) batch_1.varint_cells.extend(int_values[:2]) batch_1.string_cells = "\0".join(str_values[:2]) batch_1.is_last_batch = False batch_2 = ProtoFactory().CellsBatch() batch_2.cells.extend([ TestQueryResultIterator.CELL_STRING, TestQueryResultIterator.CELL_VARINT, TestQueryResultIterator.CELL_STRING, TestQueryResultIterator.CELL_VARINT ]) batch_2.varint_cells.extend(int_values[2:]) batch_2.string_cells = "\0".join(str_values[2:]) batch_2.is_last_batch = True # Get result from api function qr_iterator = TraceProcessor.QueryResultIterator(['foo_id', 'foo_num'], [batch_1, batch_2]) # Assert results are as expected for num, row in enumerate(qr_iterator): self.assertEqual(row.foo_id, str_values[num]) self.assertEqual(row.foo_num, int_values[num])
def test_many_batches(self): int_values = [100, 200, 300, 400] str_values = ['bar1', 'bar2', 'bar3', 'bar4'] batch_1 = ProtoFactory().CellsBatch() batch_1.cells.extend([ TestQueryResultIterator.CELL_STRING, TestQueryResultIterator.CELL_VARINT, TestQueryResultIterator.CELL_STRING, TestQueryResultIterator.CELL_VARINT ]) batch_1.varint_cells.extend(int_values[:2]) batch_1.string_cells = "\0".join(str_values[:2]) + "\0" batch_1.is_last_batch = False batch_2 = ProtoFactory().CellsBatch() batch_2.cells.extend([ TestQueryResultIterator.CELL_STRING, TestQueryResultIterator.CELL_VARINT, TestQueryResultIterator.CELL_STRING, TestQueryResultIterator.CELL_VARINT ]) batch_2.varint_cells.extend(int_values[2:]) batch_2.string_cells = "\0".join(str_values[2:]) + "\0" batch_2.is_last_batch = True qr_iterator = TraceProcessor.QueryResultIterator(['foo_id', 'foo_num'], [batch_1, batch_2]) for num, row in enumerate(qr_iterator): self.assertEqual(row.foo_id, str_values[num]) self.assertEqual(row.foo_num, int_values[num])
def test_trace_file(self): # Get path to trace_processor_shell and construct TraceProcessor tp = TraceProcessor(file_path=os.path.join( os.environ["ROOT_DIR"], 'test', 'data', 'example_android_trace_30s.pb'), bin_path=os.environ["SHELL_PATH"]) qr_iterator = tp.query('select * from slice limit 10') dur_result = [ 178646, 119740, 58073, 155000, 173177, 20209377, 3589167, 90104, 275312, 65313 ] for num, row in enumerate(qr_iterator): self.assertEqual(row.type, 'internal_slice') self.assertEqual(row.dur, dur_result[num]) tp.close()
def test_trace_file(self): # Get path to trace_processor_shell and construct TraceProcessor tp = TraceProcessor(file_path=os.path.join( os.environ["ROOT_DIR"], 'test', 'data', 'example_android_trace_30s.pb'), bin_path=os.environ["SHELL_PATH"]) qr_iterator = tp.query('select * from slice limit 10') dur_result = [ 178646, 119740, 58073, 155000, 173177, 20209377, 3589167, 90104, 275312, 65313 ] for num, row in enumerate(qr_iterator): self.assertEqual(row.type, 'internal_slice') self.assertEqual(row.dur, dur_result[num]) # Test the batching logic by issuing a large query and ensuring we receive # all rows, not just a truncated subset. qr_iterator = tp.query('select count(*) as cnt from slice') expected_count = next(qr_iterator).cnt self.assertGreater(expected_count, 0) qr_iterator = tp.query('select * from slice') count = sum(1 for _ in qr_iterator) self.assertEqual(count, expected_count) tp.close()
def test_empty_batch(self): batch = ProtoFactory().CellsBatch() batch.is_last_batch = True qr_iterator = TraceProcessor.QueryResultIterator([], [batch]) for num, row in enumerate(qr_iterator): self.assertIsNone(row.foo_id) self.assertIsNone(row.foo_num)
def test_invalid_batch_as_pandas(self): batch = ProtoFactory().CellsBatch() qr_iterator = TraceProcessor.QueryResultIterator([], [batch]) # Since the batch isn't defined as the last batch, the QueryResultsIterator # expects another batch and thus raises IndexError as no next batch exists. with self.assertRaises(IndexError): qr_df = qr_iterator.as_pandas_dataframe()
def test_empty_batch_as_pandas(self): batch = ProtoFactory().CellsBatch() batch.is_last_batch = True qr_iterator = TraceProcessor.QueryResultIterator([], [batch]) qr_df = qr_iterator.as_pandas_dataframe() for num, row in qr_df.iterrows(): self.assertEqual(row['foo_id'], str_values[num]) self.assertEqual(row['foo_num'], int_values[num])
def test_invalid_batch(self): # Create cells batch to populate QueryResult batch = ProtoFactory().CellsBatch() # Get result from api function qr_iterator = TraceProcessor.QueryResultIterator([], [batch]) # Assert results are as expected with self.assertRaises(Exception): for row in qr_iterator: pass
def test_empty_batch(self): # Create cells batch to populate QueryResult batch = ProtoFactory().CellsBatch() batch.is_last_batch = True # Get result from api function qr_iterator = TraceProcessor.QueryResultIterator([], [batch]) # Assert results are as expected for num, row in enumerate(qr_iterator): self.assertIsNone(row.foo_id) self.assertIsNone(row.foo_num)
def test_invalid_cell_type_as_pandas(self): batch = ProtoFactory().CellsBatch() batch.cells.extend([ TestQueryResultIterator.CELL_INVALID, TestQueryResultIterator.CELL_VARINT ]) batch.varint_cells.extend([100, 200]) batch.is_last_batch = True qr_iterator = TraceProcessor.QueryResultIterator(['foo_id', 'foo_num'], [batch]) # In this batch we declare the columns types to be CELL_INVALID, # CELL_VARINT but that doesn't match the data which are both ints* # so we should raise a TraceProcessorException. with self.assertRaises(TraceProcessorException): qr_df = qr_iterator.as_pandas_dataframe()
def test_incorrect_columns_batch_as_pandas(self): batch = ProtoFactory().CellsBatch() batch.cells.extend([ TestQueryResultIterator.CELL_VARINT, TestQueryResultIterator.CELL_VARINT ]) batch.varint_cells.extend([100, 200]) batch.is_last_batch = True qr_iterator = TraceProcessor.QueryResultIterator( ['foo_id', 'foo_num', 'foo_dur', 'foo_ms'], [batch]) # It's always the case that the number of cells is a multiple of the number # of columns. However, here this is clearly not the case, so when the # iterator tries to access the cell for the third column, it raises an # IndexError due to having exhausted the cells list. with self.assertRaises(IndexError): qr_df = qr_iterator.as_pandas()
def test_incorrect_columns_batch(self): int_values = [100, 200] # Create cells batch to populate QueryResult batch = ProtoFactory().CellsBatch() batch.cells.extend([ TestQueryResultIterator.CELL_VARINT, TestQueryResultIterator.CELL_VARINT ]) batch.varint_cells.extend(int_values) batch.is_last_batch = True # Get result from api function qr_iterator = TraceProcessor.QueryResultIterator( ['foo_id', 'foo_num', 'foo_dur', 'foo_ms'], [batch]) # Assert results are as expected with self.assertRaises(Exception): for row in qr_iterator: pass
def test_incorrect_cells_batch_as_pandas(self): str_values = ['bar1', 'bar2'] batch = ProtoFactory().CellsBatch() batch.cells.extend([ TestQueryResultIterator.CELL_STRING, TestQueryResultIterator.CELL_VARINT, TestQueryResultIterator.CELL_STRING, TestQueryResultIterator.CELL_VARINT ]) batch.string_cells = "\0".join(str_values) batch.is_last_batch = True qr_iterator = TraceProcessor.QueryResultIterator(['foo_id', 'foo_num'], [batch]) # The batch specifies there ought to be 2 cells of type VARINT and 2 cells # of type STRING, but there are no string cells defined in the batch. Thus # an IndexError occurs as it tries to access the empty string cells list. with self.assertRaises(IndexError): qr_df = qr_iterator.as_pandas()
def test_one_batch(self): int_values = [100, 200] str_values = ['bar1', 'bar2'] batch = ProtoFactory().CellsBatch() batch.cells.extend([ TestQueryResultIterator.CELL_STRING, TestQueryResultIterator.CELL_VARINT, TestQueryResultIterator.CELL_STRING, TestQueryResultIterator.CELL_VARINT ]) batch.varint_cells.extend(int_values) batch.string_cells = "\0".join(str_values) batch.is_last_batch = True qr_iterator = TraceProcessor.QueryResultIterator(['foo_id', 'foo_num'], [batch]) for num, row in enumerate(qr_iterator): self.assertEqual(row.foo_id, str_values[num]) self.assertEqual(row.foo_num, int_values[num])
def test_incorrect_cells_batch(self): str_values = ['bar1', 'bar2'] # Create cells batch to populate QueryResult batch = ProtoFactory().CellsBatch() batch.cells.extend([ TestQueryResultIterator.CELL_STRING, TestQueryResultIterator.CELL_VARINT, TestQueryResultIterator.CELL_STRING, TestQueryResultIterator.CELL_VARINT ]) batch.string_cells = "\0".join(str_values) batch.is_last_batch = True # Get result from api function qr_iterator = TraceProcessor.QueryResultIterator(['foo_id', 'foo_num'], [batch]) # Assert results are as expected with self.assertRaises(Exception): for row in qr_iterator: pass
def test_one_batch_as_pandas(self): int_values = [100, 200] str_values = ['bar1', 'bar2'] batch = ProtoFactory().CellsBatch() batch.cells.extend([ TestQueryResultIterator.CELL_STRING, TestQueryResultIterator.CELL_VARINT, TestQueryResultIterator.CELL_STRING, TestQueryResultIterator.CELL_VARINT ]) batch.varint_cells.extend(int_values) batch.string_cells = "\0".join(str_values) + "\0" batch.is_last_batch = True qr_iterator = TraceProcessor.QueryResultIterator(['foo_id', 'foo_num'], [batch]) qr_df = qr_iterator.as_pandas_dataframe() for num, row in qr_df.iterrows(): self.assertEqual(row['foo_id'], str_values[num]) self.assertEqual(row['foo_num'], int_values[num])
from trace_processor.api import TraceProcessor # pip install trace_processor import os path = 'test_data/android/trace/trace.pftrace' if os.path.isfile(path): tp = TraceProcessor(file_path=path) qr_it = tp.query('SELECT ts, dur, name FROM slice') for row in qr_it: print(row.ts, row.dur, row.name)
def main(): # Parse arguments passed from command line parser = argparse.ArgumentParser() parser.add_argument( "-a", "--address", help= "Address at which trace_processor is being run, e.g. localhost:9001", type=str) parser.add_argument("-b", "--binary", help="Absolute path to a trace processor binary", type=str) parser.add_argument("-f", "--file", help="Absolute path to trace", type=str) args = parser.parse_args() # Pass arguments into api to construct the trace processor and load the trace if args.address is None and args.file is None: raise Exception("You must specify an address or a file path to trace") elif args.address is None: tp = TraceProcessor(file_path=args.file, bin_path=args.binary) elif args.file is None: tp = TraceProcessor(addr=args.address) else: tp = TraceProcessor(addr=args.address, file_path=args.file, bin_path=args.binary) # Iterate through QueryResultIterator res_it = tp.query('select * from slice limit 10') for row in res_it: print(row.name) # Convert QueryResultIterator into a pandas dataframe + iterate. This yields # the same results as the function above. try: res_df = tp.query('select * from slice limit 10').as_pandas() for index, row in res_df.iterrows(): print(row['name']) except Exception: pass # Call another function on the loaded trace am_metrics = tp.metric(['android_mem']) tp.close()
current[row.name] = row.value if len(current) == len(counters): groups[ts] = current print( f"Bottleneck for rule: {correlation['name']} found in frames: {frames}" ) def analyze_trace(tp, spec, package_name, api): stats, frame_numbers = get_frame_time_stats(tp, package_name, api) pprint.pprint(stats) cors = spec['correlations'] for cor in cors: query_str = build_query(cor) print(query_str) qr_it = tp.query(query_str) analyze_query(qr_it, cor, frame_numbers) if __name__ == '__main__': if len(sys.argv) == 5: spec = load_spec(sys.argv[2]) tp = TraceProcessor(file_path=sys.argv[1]) analyze_trace(tp, spec, sys.argv[3], sys.argv[4]) # print(spec) else: print( "Incorrect arguments: 'python3 analyze.py trace.perfetto spec/specname.json com.package.name api'" )