Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
perf-compare.py 2.56 KiB
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from pathlib import Path
import matplotlib
matplotlib.use('Agg')
from matplotlib import pyplot as pl
from typing import List, Tuple
import pandas as pd

def read_json_metrics(fname: Path) -> pd.DataFrame:
    import json
    xs = []
    for x in json.load(fname.open('rb')):
        name, value = x
        sample = ('//'.join(name), value)
        xs.append(sample)

    return pd.DataFrame(xs, columns=['name', 'value'])

def read_csv_metrics(fname: Path) -> pd.DataFrame:
    return pd.read_csv(fname, delimiter='\t', names=['name','value'])

def read_metrics(fname: Path) -> pd.DataFrame:
    path = Path(fname.name)
    if path.suffix == '.json':
        return read_json_metrics(path)
    else:
        return read_csv_metrics(path)

def main() -> None:
    import argparse
    parser = argparse.ArgumentParser()
    parser.add_argument('file', nargs='+', type=argparse.FileType('r'), help='CSV metrics file')
    parser.add_argument('-m', '--metric', type=str, nargs='+', help='Metrics to plot')
    parser.add_argument('-l', '--list', action='store_true', help='List all metrics')
    parser.add_argument('--bins', type=int, default=100, help='Number of histogram bins')
    parser.add_argument('--min', type=float, help='Histogram minimum')
    parser.add_argument('--max', type=float, help='Histogram maximum')
    args = parser.parse_args()

    files = pd.concat(
        read_metrics(f).assign(file=f.name)
        for f in args.file
    )

    all_metrics = set(files.loc[:,'name'].unique())

    if args.list:
        print('\n'.join(sorted(all_metrics)))
    else:
        # plot
        if args.metric:
            to_plot = args.metric
            missing_metrics = set(args.metric) - all_metrics
            if len(missing_metrics) > 0:
               print('No files contain the metrics:')
               print(', '.join(missing_metrics))
        else:
            to_plot = all_metrics


        for metric in to_plot:
            pl.clf()
            xs = files.loc[files['name'] == metric]
            min_bound = args.min if args.min else xs['value'].min()
            max_bound = args.max if args.max else xs['value'].max()
            bounds = (min_bound, max_bound)
            for name, values in xs.groupby('file'):
                pl.hist(values['value'], label=name, bins=args.bins, range=bounds, alpha=0.6)

            pl.ylabel('number of occurrences')
            pl.xlabel(metric)
            pl.legend()
            out = metric.replace('//', '-').replace('/', '_')
            pl.savefig(f'{out}.svg')

if __name__ == '__main__':
    main()