Message ID | 20201028103151.34575-5-paul.elder@ideasonboard.com |
---|---|
State | Accepted |
Headers | show |
Series |
|
Related | show |
Hi Paul, Thank you for the patch. On Wed, Oct 28, 2020 at 07:31:50PM +0900, Paul Elder wrote: > 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> > > --- > New in v2 > --- > utils/tracepoints/analyze.py | 64 ++++++++++++++++++++++++++++++++++++ > 1 file changed, 64 insertions(+) > create mode 100755 utils/tracepoints/analyze.py > > diff --git a/utils/tracepoints/analyze.py b/utils/tracepoints/analyze.py > new file mode 100755 > index 00000000..be56ca28 > --- /dev/null > +++ b/utils/tracepoints/analyze.py > @@ -0,0 +1,64 @@ > +#!/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.py - Analysis tool for libcamera lttng output Maybe mention this is meant as a simple example to show how information can be extracted from 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() > + 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') Good you expand this with documentation to allow someone who runs the script with --help to understand what it can be used for, and how ? > + args = parser.parse_args(argv[1:]) > + > + traces = bt2.TraceCollectionMessageIterator(args.trace_path) > + for msg in traces: > + if type(msg) is not bt2._EventMessageConst 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"] s/"/'/g > + timestamp_ns = msg.default_clock_snapshot.ns_from_origin > + > + if event == 'libcamera:ipa_call_start': > + 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_finish': > + ts = timestamps[pipeline][func].pop() > + key = f'{pipeline}:{func}' > + if key not in samples: > + samples[key] = [] > + samples[key].append(timestamp_ns - ts) > + > + print('pipeline:function\t:\tmin\tmax\tmean\tstddev') > + for k, v in samples.items(): > + mean = int(stats.mean(v)) > + stddev = int(stats.stdev(v)) > + minv = min(v) > + maxv = max(v) > + print(f'{k}\t:\t{minv}\t{maxv}\t{mean}\t{stddev}') A small enhancement, if you have time, to make it easier to read, would be to align fields in different lines. That would require storing the fields in text form for all lines first, then computing the max string length for each field, and then print them accordingly. > + > + > +if __name__ == '__main__': > + sys.exit(main(sys.argv))
diff --git a/utils/tracepoints/analyze.py b/utils/tracepoints/analyze.py new file mode 100755 index 00000000..be56ca28 --- /dev/null +++ b/utils/tracepoints/analyze.py @@ -0,0 +1,64 @@ +#!/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.py - Analysis tool for libcamera lttng output + +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() + 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') + args = parser.parse_args(argv[1:]) + + traces = bt2.TraceCollectionMessageIterator(args.trace_path) + for msg in traces: + if type(msg) is not bt2._EventMessageConst 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_start': + 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_finish': + ts = timestamps[pipeline][func].pop() + key = f'{pipeline}:{func}' + if key not in samples: + samples[key] = [] + samples[key].append(timestamp_ns - ts) + + print('pipeline:function\t:\tmin\tmax\tmean\tstddev') + for k, v in samples.items(): + mean = int(stats.mean(v)) + stddev = int(stats.stdev(v)) + minv = min(v) + maxv = max(v) + print(f'{k}\t:\t{minv}\t{maxv}\t{mean}\t{stddev}') + + +if __name__ == '__main__': + sys.exit(main(sys.argv))
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> --- New in v2 --- utils/tracepoints/analyze.py | 64 ++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100755 utils/tracepoints/analyze.py