From patchwork Fri Oct 30 08:57:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 10309 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id AC1D9BDB1E for ; Fri, 30 Oct 2020 08:58:14 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 7379C62993; Fri, 30 Oct 2020 09:58:14 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="uPCmpeiW"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C92D462989 for ; Fri, 30 Oct 2020 09:58:12 +0100 (CET) Received: from pyrite.rasen.tech (unknown [IPv6:2400:4051:61:600:2c71:1b79:d06d:5032]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 62DD69B7; Fri, 30 Oct 2020 09:58:11 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1604048292; bh=NggESQQjOGLezqZG4Eaf/+OnHf4qqL3sgBns2AH90LI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=uPCmpeiWetgZYG4I6W68kZ1KA6HvHv77CKjzEH2mSscZMA4sNqmaxWooaip/ORoed H7hLDEa2/n7odRXHp8jwLTTlEjvwrPr8tLbd9blKRRKfmzTgku+mr8uXHo/EpQIcjO 2rL8CvxamzuTVSKb1nFnOGfFt/Fi63C27g1JESJU= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Fri, 30 Oct 2020 17:57:55 +0900 Message-Id: <20201030085756.79329-5-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201030085756.79329-1-paul.elder@ideasonboard.com> References: <20201030085756.79329-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 4/5] utils: tracepoints: Add simple statistics script X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" 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 Reviewed-by: Laurent Pinchart --- 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 +# +# 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))