diff options
author | Paul Elder <paul.elder@ideasonboard.com> | 2020-10-28 19:06:00 +0900 |
---|---|---|
committer | Paul Elder <paul.elder@ideasonboard.com> | 2020-11-03 11:33:41 +0900 |
commit | 6e77b59055a79a0d32ac96bdef73357c9c084c30 (patch) | |
tree | c00523ad7a5c93f2025db49b8d77db4f9f01fb95 /utils/tracepoints | |
parent | 27c9d6eceb15b8a4e400fd2b053fb84d0db10da4 (diff) |
utils: tracepoints: Add simple statistics script
Add a script that scans a trace for IPA call tracepoints, and returns
statistics on the time taken for IPA calls.
Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Diffstat (limited to 'utils/tracepoints')
-rwxr-xr-x | utils/tracepoints/analyze-ipa-trace.py | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/utils/tracepoints/analyze-ipa-trace.py b/utils/tracepoints/analyze-ipa-trace.py new file mode 100755 index 00000000..50fbbf42 --- /dev/null +++ b/utils/tracepoints/analyze-ipa-trace.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020, Google Inc. +# +# Author: Paul Elder <paul.elder@ideasonboard.com> +# +# analyze-ipa-trace.py - Example of how to extract information from libcamera lttng traces + +import argparse +import bt2 +import statistics as stats +import sys + +# pipeline -> {function -> stack(timestamps)} +timestamps = {} + +# pipeline:function -> samples[] +samples = {} + +def main(argv): + parser = argparse.ArgumentParser( + description='A simple analysis script to get statistics on time taken for IPA calls') + parser.add_argument('-p', '--pipeline', type=str, + help='Name of pipeline to filter for') + parser.add_argument('trace_path', type=str, + help='Path to lttng trace (eg. ~/lttng-traces/demo-20201029-184003)') + args = parser.parse_args(argv[1:]) + + traces = bt2.TraceCollectionMessageIterator(args.trace_path) + for msg in traces: + if type(msg) is not bt2._EventMessageConst or \ + 'pipeline_name' not in msg.event.payload_field or \ + (args.pipeline is not None and \ + msg.event.payload_field['pipeline_name'] != args.pipeline): + continue + + pipeline = msg.event.payload_field['pipeline_name'] + event = msg.event.name + func = msg.event.payload_field['function_name'] + timestamp_ns = msg.default_clock_snapshot.ns_from_origin + + if event == 'libcamera:ipa_call_begin': + if pipeline not in timestamps: + timestamps[pipeline] = {} + if func not in timestamps[pipeline]: + timestamps[pipeline][func] = [] + timestamps[pipeline][func].append(timestamp_ns) + + if event == 'libcamera:ipa_call_end': + ts = timestamps[pipeline][func].pop() + key = f'{pipeline}:{func}' + if key not in samples: + samples[key] = [] + samples[key].append(timestamp_ns - ts) + + # Compute stats + rows = [] + rows.append(['pipeline:function', 'min', 'max', 'mean', 'stddev']) + for k, v in samples.items(): + mean = int(stats.mean(v)) + stddev = int(stats.stdev(v)) + minv = min(v) + maxv = max(v) + rows.append([k, str(minv), str(maxv), str(mean), str(stddev)]) + + # Get maximum string width for every column + widths = [] + for i in range(len(rows[0])): + widths.append(max([len(row[i]) for row in rows])) + + # Print stats table + for row in rows: + fmt = [row[i].rjust(widths[i]) for i in range(1, 5)] + print('{} {} {} {} {}'.format(row[0].ljust(widths[0]), *fmt)) + +if __name__ == '__main__': + sys.exit(main(sys.argv)) |