[libcamera-devel] [PATCH v4 4/5] utils: tracepoints: Add simple statistics script
Laurent Pinchart
laurent.pinchart at ideasonboard.com
Tue Nov 3 01:30:52 CET 2020
Hi Paul,
Thank you for the patch.
On Fri, Oct 30, 2020 at 05:57:55PM +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 at ideasonboard.com>
>
> ---
> Changes in v4:
> - rename script to analyze-ipa-trace.py
> - align output stats table
>
> Changes in v3:
> - check for the new tracepoint names, ipa_call_begin and ipa_call_end
> - fix babeltrace2 parsing in the case that the event doesn't have a
> pipeline_name field
> - change script description
> - add argparse description
> - add example for trace_path argument
> - change double quotes to single quotes
>
> New in v2
> ---
> utils/tracepoints/analyze-ipa-trace.py | 77 ++++++++++++++++++++++++++
> 1 file changed, 77 insertions(+)
> create mode 100755 utils/tracepoints/analyze-ipa-trace.py
>
> 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 at 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]))
You can write this
widths.append(max(len(row[i]) for row in rows))
and python will create a generator for the expression passed to max(),
instead of creating an actual list.
And I've now tried to measure the efficiency, and the generator is
slower -_-'. Let's ignore this.
> +
> + # 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))
You've made all the code here independent of the number of columns,
except for the format string :-) No big deal though.
Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> +
> +if __name__ == '__main__':
> + sys.exit(main(sys.argv))
--
Regards,
Laurent Pinchart
More information about the libcamera-devel
mailing list