#!/usr/bin/python3 """ NNAPI benchmark output parser (statistics aggregator) Reads a file with output from multiple runs of adb shell am instrument -w com.android.nn.benchmark.app/androidx.test.runner.AndroidJUnitRunner and provides either raw measurements or aggregated statistics of the runs. Usage: parse_benchmark --format=[json|table] --output=[full|stats] [adb output filename] """ import argparse import json import statistics FLAG_FORMAT_JSON = "json" FLAG_FORMAT_TABLE = "table" FLAG_OUTPUT_FULL = "full" FLAG_OUTPUT_STATS = "stats" def main(): parser = argparse.ArgumentParser() parser.add_argument("input", help="input filename") parser.add_argument("--format", help="output format ({0}|{1})" .format(FLAG_FORMAT_TABLE, FLAG_FORMAT_JSON), default=FLAG_FORMAT_TABLE) parser.add_argument("--output", help="output data ({0}|{1})" .format(FLAG_OUTPUT_FULL, FLAG_OUTPUT_STATS), default=FLAG_OUTPUT_STATS) args = parser.parse_args() data = read_data(args.input) if args.output == FLAG_OUTPUT_STATS: stats = compute_stats(data) print_stats(stats, args.format) else: print_data(data, args.format) def read_data(input_filename): data = dict() with open(input_filename) as f: for line in f: if "INSTRUMENTATION_STATUS:" in line and "_avg" in line: sample = line.split(": ")[1] name, value = sample.split("=") name = name[:-4] data[name] = data.get(name, []) + [float(value)] return data def compute_stats(data): stats = list() for name in sorted(data): values = data[name] stat_mean = statistics.mean(values) stat_stdev = statistics.stdev(values) stat_min = min(values) stat_max = max(values) stat_n = len(values) stats.append({"benchmark": name, "mean": stat_mean, "stddev": stat_stdev, "min": stat_min, "max": stat_max, "n": stat_n}) return stats def print_stats(stats, print_format): if print_format == FLAG_FORMAT_TABLE: print("{0:<34}{1:>10}{2:>10}{3:>10}{4:>10}{5:>10}".format( "Benchmark", "mean", "stddev", "min", "max", "n")) for line in stats: print("{0:<34}{1:>10.2f}{2:>10.2f}{3:>10.2f}{4:>10.2f}{5:>10d}".format( line["benchmark"], line["mean"], line["stddev"], line["min"], line["max"], line["n"])) else: print(json.dumps(stats)) def print_data(data, print_format): if print_format == FLAG_FORMAT_TABLE: print("{0:<34}{1:>10}".format( "Benchmark", "sample")) for name in data: for sample in data[name]: if print_format == FLAG_FORMAT_TABLE: print("{0:<34}{1:>10}".format(name, sample)) else: print(json.dumps({"benchmark": name, "sample": sample})) if __name__ == "__main__": main()