| #!/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() |