v2: rework --top and --smallest v2: add --affected option v2: make the summary after the affected program lists
Signed-off-by: Rhys Perry <pendingchao...@gmail.com> --- nv-report.py | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 117 insertions(+), 2 deletions(-) diff --git a/nv-report.py b/nv-report.py index 1894f91409..4f4150a4cb 100644 --- a/nv-report.py +++ b/nv-report.py @@ -12,6 +12,7 @@ fields, except for the type, are optional. import re import sys +import random import argparse @@ -79,13 +80,18 @@ def read_stats(fname): return stats -def diff(a, b): +def get_diff_percentage(a, b): percentage = 0. if a != 0.: percentage = b * 100. / a - 100. elif b != 0.: percentage = float('inf') - return "%d -> %d (%.2f%%)" % (a, b, percentage) + return percentage + +def diff(a, b): + return "%d -> %d (%.2f%%)" % (a, b, get_diff_percentage(a, b)) + +# summary def print_summary(before, after, keys, only_affected): if only_affected: @@ -135,10 +141,109 @@ def print_helped_hurt(keys, before, after): print "%10d " % getattr(hurt, attr), print +# --smallest, --affected and --top options + +def iter_affected(before, after, keys, attrs, only_hurt): + for key in keys: + a = after.stats[key] + b = before.stats[key] + affected = False + hurt = False + for attr in attrs if isinstance(attrs, list) else [attrs]: + aa = getattr(a, attr) + ba = getattr(b, attr) + if aa != ba: + affected = True + if aa > ba: + hurt = True + if only_hurt and not hurt: + continue + if affected: + yield key, b, a + +def print_affected_list(args, fmt, attrs, print_size, affected): + message = fmt % len(affected) + if args.only_hurt: + message += "hurt" + else: + message += "affected" + message += " programs for " + ', '.join(attrs) + print message + + for key, _, b, a in affected: + if print_size: + print " %d inst : " % a.inst + key + else: + print " " + key + for attr in attrs: + ba = getattr(b, attr) + aa = getattr(a, attr) + if ba != aa: + print " %s : %s" % (attr, diff(ba, aa)) + print + +def parse_list_opt(arg): + try: + num = int(arg[0]) + attrs = arg[1:] + except Exception: + num = None # l[:None] == l + attrs = arg + if len(attrs) == 0: + attrs = STATS + return num, attrs + +def print_affected(before, after, keys, args, arg): + num, attrs = parse_list_opt(arg) + + affected = iter_affected(before, after, keys, attrs, args.only_hurt) + affected = [(key, None, b, a) for key, b, a in affected] + random.shuffle(affected) + affected = affected[:num] + + print_affected_list(args, "%d random ", attrs, False, affected) + +def print_top(before, after, keys, args, arg): + num, attrs = parse_list_opt(arg) + attrs = [attrs[0]] + + candidates = [] + for key, b, a in iter_affected(before, after, keys, attrs, args.only_hurt): + ba = getattr(b, attrs[0]) + aa = getattr(a, attrs[0]) + score = abs(get_diff_percentage(ba, aa)) + if args.scale_size: + score /= float(after.stats[key].inst) + candidates.append((key, score, b, a)) + candidates.sort(key = lambda a: a[1], reverse=True) + candidates = candidates[:num] + + print_affected_list(args, "top %d ", attrs, False, candidates) + +def print_smallest(before, after, keys, args, arg): + num, attrs = parse_list_opt(arg) + + affected_iter = iter_affected(before, after, keys, attrs, args.only_hurt) + candidates = [(key, after.stats[key].inst, b, a) for key, b, a, in affected_iter] + candidates.sort(key = lambda a: a[1]) + candidates = candidates[:num] + + print_affected_list(args, "smallest %d ", attrs, True, candidates) + def main(argv): parser = argparse.ArgumentParser(description=DESCRIPTION) parser.add_argument('before', help="the baseline run") parser.add_argument('after', help="the run to compare against the baseline") + parser.add_argument("--top", action="append", nargs='+', metavar=("N", "ATTR"), + help="also show the top n (or all) programs affected by the first ATTR") + parser.add_argument('--smallest', action="append", nargs='*', metavar=("N", "ATTR"), + help="also show the smallest n (or all) programs affected") + parser.add_argument('--affected', action="append", nargs='*', metavar=("N", "ATTR"), + help="also show n (or all) affected programs in a random order (note that N is not needed for ATTR)") + parser.add_argument('--scale_size', action="store_true", + help="scale the score for --top by the program size so smaller ones are first") + parser.add_argument('--only_hurt', action="store_true", + help="only show hurt programs for --smallest, --affected and --small_affected") args = parser.parse_args(argv[1:]) before = read_stats(args.before) @@ -151,6 +256,15 @@ def main(argv): continue keys.add(key) + for arg in args.affected or []: + print_affected(before, after, keys, args, arg) + + for arg in args.top or []: + print_top(before, after, keys, args, arg) + + for arg in args.smallest or []: + print_smallest(before, after, keys, args, arg) + print_summary(before, after, keys, True) print print_summary(before, after, keys, False) @@ -159,4 +273,5 @@ def main(argv): if __name__ == "__main__": + random.seed(0) main(sys.argv) -- 2.14.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev