scripts: Added -c/--compare for comparing specific result rows

Example:

  $ ./scripts/csv.py lfs.code.csv \
          -bfunction -fsize \
          -clfsr_rbyd_appendrattr
  function                                size
  lfsr_rbyd_appendrattr                   3598
  lfsr_mdir_commit                        5176 (+43.9%)
  lfsr_btree_commit__.constprop.0         3955 (+9.9%)
  lfsr_file_flush_                        2729 (-24.2%)
  lfsr_file_carve                         2503 (-30.4%)
  lfsr_mountinited                        2357 (-34.5%)
  ... snip ...

I don't think this is immediately useful for our code/stack/etc
measurement scripts, but it's certainly useful in csv.py for comparing
results at a high level.

And by useful I mean it replaces a 40-line long awk script that has
outgrown its original purpose...
This commit is contained in:
Christopher Haster
2024-11-14 11:52:59 -06:00
parent 14687a20bf
commit 29eff6f3e8
8 changed files with 386 additions and 80 deletions

View File

@@ -378,6 +378,7 @@ def table(Result, results, diff_results=None, *,
summary=False,
all=False,
percent=False,
compare=None,
**_):
all_, all = all, __builtins__.all
@@ -409,8 +410,22 @@ def table(Result, results, diff_results=None, *,
getattr(diff_table.get(name), k, None))
for k in fields)]
# find compare entry if there is one
if compare is not None:
compare_result = table.get(','.join(str(k) for k in compare))
# sort again, now with diff info, note that python's sort is stable
names.sort()
if compare is not None:
names.sort(
key=lambda n: (
table.get(n) == compare_result,
tuple(
types[k].ratio(
getattr(table.get(n), k, None),
getattr(compare_result, k, None))
for k in fields)),
reverse=True)
if diff_results is not None:
names.sort(
key=lambda n: tuple(
@@ -462,14 +477,30 @@ def table(Result, results, diff_results=None, *,
# entry helper
def table_entry(name, r, diff_r=None):
entry = [name]
if diff_results is None:
# normal entry?
if ((compare is None or r == compare_result)
and diff_results is None):
for k in fields:
entry.append(
(getattr(r, k).table(),
getattr(getattr(r, k), 'notes', lambda: [])())
if getattr(r, k, None) is not None
else types[k].none)
elif percent:
# compare entry?
elif compare is not None and diff_results is None:
for k in fields:
entry.append(
(getattr(r, k).table()
if getattr(r, k, None) is not None
else types[k].none,
(lambda t: ['+∞%'] if t == +mt.inf
else ['-∞%'] if t == -mt.inf
else ['%+.1f%%' % (100*t)])(
types[k].ratio(
getattr(r, k, None),
getattr(compare_result, k, None)))))
# percent entry?
elif diff_results is not None and percent:
for k in fields:
entry.append(
(getattr(r, k).table()
@@ -481,7 +512,8 @@ def table(Result, results, diff_results=None, *,
types[k].ratio(
getattr(r, k, None),
getattr(diff_r, k, None)))))
else:
# diff entry?
elif diff_results is not None:
for k in fields:
entry.append(getattr(diff_r, k).table()
if getattr(diff_r, k, None) is not None
@@ -514,7 +546,8 @@ def table(Result, results, diff_results=None, *,
diff_r = diff_table.get(name)
lines.append(table_entry(name, r, diff_r))
# total
# total, unless we're comparing
if summary or not (compare is not None and diff_results is None):
r = next(iter(fold(Result, results, by=[])), None)
if diff_results is None:
diff_r = None
@@ -679,6 +712,10 @@ if __name__ == "__main__":
'-p', '--percent',
action='store_true',
help="Only show percentage change, not a full diff.")
parser.add_argument(
'-c', '--compare',
type=lambda x: tuple(v.strip() for v in x.split(',')),
help="Compare results to the row matching this by pattern.")
parser.add_argument(
'-b', '--by',
action='append',

View File

@@ -388,6 +388,7 @@ def table(Result, results, diff_results=None, *,
summary=False,
all=False,
percent=False,
compare=None,
**_):
all_, all = all, __builtins__.all
@@ -419,8 +420,22 @@ def table(Result, results, diff_results=None, *,
getattr(diff_table.get(name), k, None))
for k in fields)]
# find compare entry if there is one
if compare is not None:
compare_result = table.get(','.join(str(k) for k in compare))
# sort again, now with diff info, note that python's sort is stable
names.sort()
if compare is not None:
names.sort(
key=lambda n: (
table.get(n) == compare_result,
tuple(
types[k].ratio(
getattr(table.get(n), k, None),
getattr(compare_result, k, None))
for k in fields)),
reverse=True)
if diff_results is not None:
names.sort(
key=lambda n: tuple(
@@ -472,14 +487,30 @@ def table(Result, results, diff_results=None, *,
# entry helper
def table_entry(name, r, diff_r=None):
entry = [name]
if diff_results is None:
# normal entry?
if ((compare is None or r == compare_result)
and diff_results is None):
for k in fields:
entry.append(
(getattr(r, k).table(),
getattr(getattr(r, k), 'notes', lambda: [])())
if getattr(r, k, None) is not None
else types[k].none)
elif percent:
# compare entry?
elif compare is not None and diff_results is None:
for k in fields:
entry.append(
(getattr(r, k).table()
if getattr(r, k, None) is not None
else types[k].none,
(lambda t: ['+∞%'] if t == +mt.inf
else ['-∞%'] if t == -mt.inf
else ['%+.1f%%' % (100*t)])(
types[k].ratio(
getattr(r, k, None),
getattr(compare_result, k, None)))))
# percent entry?
elif diff_results is not None and percent:
for k in fields:
entry.append(
(getattr(r, k).table()
@@ -491,7 +522,8 @@ def table(Result, results, diff_results=None, *,
types[k].ratio(
getattr(r, k, None),
getattr(diff_r, k, None)))))
else:
# diff entry?
elif diff_results is not None:
for k in fields:
entry.append(getattr(diff_r, k).table()
if getattr(diff_r, k, None) is not None
@@ -524,7 +556,8 @@ def table(Result, results, diff_results=None, *,
diff_r = diff_table.get(name)
lines.append(table_entry(name, r, diff_r))
# total
# total, unless we're comparing
if summary or not (compare is not None and diff_results is None):
r = next(iter(fold(Result, results, by=[])), None)
if diff_results is None:
diff_r = None
@@ -791,6 +824,10 @@ if __name__ == "__main__":
'-p', '--percent',
action='store_true',
help="Only show percentage change, not a full diff.")
parser.add_argument(
'-c', '--compare',
type=lambda x: tuple(v.strip() for v in x.split(',')),
help="Compare results to the row matching this by pattern.")
parser.add_argument(
'-b', '--by',
action='append',

View File

@@ -1403,6 +1403,7 @@ def table(Result, results, diff_results=None, *,
summary=False,
all=False,
percent=False,
compare=None,
**_):
all_, all = all, __builtins__.all
@@ -1434,8 +1435,32 @@ def table(Result, results, diff_results=None, *,
getattr(diff_table.get(name), k, None))
for k in fields)]
# find compare entry if there is one
if compare is not None:
compare_result = table.get(','.join(str(k) for k in compare))
# sort again, now with diff info, note that python's sort is stable
names.sort()
if compare is not None:
names.sort(
key=lambda n: (
table.get(n) == compare_result,
tuple(
types[k].ratio(
getattr(table.get(n), k, None),
getattr(compare_result, k, None))
for k in fields)),
reverse=True)
if compare is not None:
names.sort(
key=lambda n: (
table.get(n) == compare_result,
tuple(
types[k].ratio(
getattr(table.get(n), k, None),
getattr(compare_result, k, None))
for k in fields)),
reverse=True)
if diff_results is not None:
names.sort(
key=lambda n: tuple(
@@ -1487,14 +1512,30 @@ def table(Result, results, diff_results=None, *,
# entry helper
def table_entry(name, r, diff_r=None):
entry = [name]
if diff_results is None:
# normal entry?
if ((compare is None or r == compare_result)
and diff_results is None):
for k in fields:
entry.append(
(getattr(r, k).table(),
getattr(getattr(r, k), 'notes', lambda: [])())
if getattr(r, k, None) is not None
else types[k].none)
elif percent:
# compare entry?
elif compare is not None and diff_results is None:
for k in fields:
entry.append(
(getattr(r, k).table()
if getattr(r, k, None) is not None
else types[k].none,
(lambda t: ['+∞%'] if t == +mt.inf
else ['-∞%'] if t == -mt.inf
else ['%+.1f%%' % (100*t)])(
types[k].ratio(
getattr(r, k, None),
getattr(compare_result, k, None)))))
# percent entry?
elif diff_results is not None and percent:
for k in fields:
entry.append(
(getattr(r, k).table()
@@ -1506,7 +1547,8 @@ def table(Result, results, diff_results=None, *,
types[k].ratio(
getattr(r, k, None),
getattr(diff_r, k, None)))))
else:
# diff entry?
elif diff_results is not None:
for k in fields:
entry.append(getattr(diff_r, k).table()
if getattr(diff_r, k, None) is not None
@@ -1539,7 +1581,8 @@ def table(Result, results, diff_results=None, *,
diff_r = diff_table.get(name)
lines.append(table_entry(name, r, diff_r))
# total
# total, unless we're comparing
if summary or not (compare is not None and diff_results is None):
r = next(iter(fold(Result, results, by=[])), None)
if diff_results is None:
diff_r = None
@@ -1708,6 +1751,10 @@ if __name__ == "__main__":
'-p', '--percent',
action='store_true',
help="Only show percentage change, not a full diff.")
parser.add_argument(
'-c', '--compare',
type=lambda x: tuple(v.strip() for v in x.split(',')),
help="Compare results to the row matching this by pattern.")
parser.add_argument(
'-b', '--by',
action='append',

View File

@@ -378,6 +378,7 @@ def table(Result, results, diff_results=None, *,
summary=False,
all=False,
percent=False,
compare=None,
**_):
all_, all = all, __builtins__.all
@@ -409,8 +410,22 @@ def table(Result, results, diff_results=None, *,
getattr(diff_table.get(name), k, None))
for k in fields)]
# find compare entry if there is one
if compare is not None:
compare_result = table.get(','.join(str(k) for k in compare))
# sort again, now with diff info, note that python's sort is stable
names.sort()
if compare is not None:
names.sort(
key=lambda n: (
table.get(n) == compare_result,
tuple(
types[k].ratio(
getattr(table.get(n), k, None),
getattr(compare_result, k, None))
for k in fields)),
reverse=True)
if diff_results is not None:
names.sort(
key=lambda n: tuple(
@@ -462,14 +477,30 @@ def table(Result, results, diff_results=None, *,
# entry helper
def table_entry(name, r, diff_r=None):
entry = [name]
if diff_results is None:
# normal entry?
if ((compare is None or r == compare_result)
and diff_results is None):
for k in fields:
entry.append(
(getattr(r, k).table(),
getattr(getattr(r, k), 'notes', lambda: [])())
if getattr(r, k, None) is not None
else types[k].none)
elif percent:
# compare entry?
elif compare is not None and diff_results is None:
for k in fields:
entry.append(
(getattr(r, k).table()
if getattr(r, k, None) is not None
else types[k].none,
(lambda t: ['+∞%'] if t == +mt.inf
else ['-∞%'] if t == -mt.inf
else ['%+.1f%%' % (100*t)])(
types[k].ratio(
getattr(r, k, None),
getattr(compare_result, k, None)))))
# percent entry?
elif diff_results is not None and percent:
for k in fields:
entry.append(
(getattr(r, k).table()
@@ -481,7 +512,8 @@ def table(Result, results, diff_results=None, *,
types[k].ratio(
getattr(r, k, None),
getattr(diff_r, k, None)))))
else:
# diff entry?
elif diff_results is not None:
for k in fields:
entry.append(getattr(diff_r, k).table()
if getattr(diff_r, k, None) is not None
@@ -514,7 +546,8 @@ def table(Result, results, diff_results=None, *,
diff_r = diff_table.get(name)
lines.append(table_entry(name, r, diff_r))
# total
# total, unless we're comparing
if summary or not (compare is not None and diff_results is None):
r = next(iter(fold(Result, results, by=[])), None)
if diff_results is None:
diff_r = None
@@ -676,6 +709,10 @@ if __name__ == "__main__":
'-p', '--percent',
action='store_true',
help="Only show percentage change, not a full diff.")
parser.add_argument(
'-c', '--compare',
type=lambda x: tuple(v.strip() for v in x.split(',')),
help="Compare results to the row matching this by pattern.")
parser.add_argument(
'-b', '--by',
action='append',

View File

@@ -694,6 +694,7 @@ def table(Result, results, diff_results=None, *,
summary=False,
all=False,
percent=False,
compare=None,
depth=None,
hot=None,
**_):
@@ -755,8 +756,22 @@ def table(Result, results, diff_results=None, *,
getattr(diff_table.get(name), k, None))
for k in fields)]
# find compare entry if there is one
if compare is not None:
compare_result = table.get(','.join(str(k) for k in compare))
# sort again, now with diff info, note that python's sort is stable
names.sort()
if compare is not None:
names.sort(
key=lambda n: (
table.get(n) == compare_result,
tuple(
types[k].ratio(
getattr(table.get(n), k, None),
getattr(compare_result, k, None))
for k in fields)),
reverse=True)
if diff_results is not None:
names.sort(
key=lambda n: tuple(
@@ -808,14 +823,30 @@ def table(Result, results, diff_results=None, *,
# entry helper
def table_entry(name, r, diff_r=None):
entry = [name]
if diff_results is None:
# normal entry?
if ((compare is None or r == compare_result)
and diff_results is None):
for k in fields:
entry.append(
(getattr(r, k).table(),
getattr(getattr(r, k), 'notes', lambda: [])())
if getattr(r, k, None) is not None
else types[k].none)
elif percent:
# compare entry?
elif compare is not None and diff_results is None:
for k in fields:
entry.append(
(getattr(r, k).table()
if getattr(r, k, None) is not None
else types[k].none,
(lambda t: ['+∞%'] if t == +mt.inf
else ['-∞%'] if t == -mt.inf
else ['%+.1f%%' % (100*t)])(
types[k].ratio(
getattr(r, k, None),
getattr(compare_result, k, None)))))
# percent entry?
elif diff_results is not None and percent:
for k in fields:
entry.append(
(getattr(r, k).table()
@@ -827,7 +858,8 @@ def table(Result, results, diff_results=None, *,
types[k].ratio(
getattr(r, k, None),
getattr(diff_r, k, None)))))
else:
# diff entry?
elif diff_results is not None:
for k in fields:
entry.append(getattr(diff_r, k).table()
if getattr(diff_r, k, None) is not None
@@ -923,7 +955,8 @@ def table(Result, results, diff_results=None, *,
"| ",
" "))
# total
# total, unless we're comparing
if summary or not (compare is not None and diff_results is None):
r = next(iter(fold(Result, results, by=[])), None)
if diff_results is None:
diff_r = None
@@ -1233,6 +1266,10 @@ if __name__ == "__main__":
'-p', '--percent',
action='store_true',
help="Only show percentage change, not a full diff.")
parser.add_argument(
'-c', '--compare',
type=lambda x: tuple(v.strip() for v in x.split(',')),
help="Compare results to the row matching this by pattern.")
parser.add_argument(
'-b', '--by',
action='append',

View File

@@ -658,6 +658,7 @@ def table(Result, results, diff_results=None, *,
summary=False,
all=False,
percent=False,
compare=None,
depth=None,
hot=None,
**_):
@@ -719,8 +720,22 @@ def table(Result, results, diff_results=None, *,
getattr(diff_table.get(name), k, None))
for k in fields)]
# find compare entry if there is one
if compare is not None:
compare_result = table.get(','.join(str(k) for k in compare))
# sort again, now with diff info, note that python's sort is stable
names.sort()
if compare is not None:
names.sort(
key=lambda n: (
table.get(n) == compare_result,
tuple(
types[k].ratio(
getattr(table.get(n), k, None),
getattr(compare_result, k, None))
for k in fields)),
reverse=True)
if diff_results is not None:
names.sort(
key=lambda n: tuple(
@@ -772,14 +787,30 @@ def table(Result, results, diff_results=None, *,
# entry helper
def table_entry(name, r, diff_r=None):
entry = [name]
if diff_results is None:
# normal entry?
if ((compare is None or r == compare_result)
and diff_results is None):
for k in fields:
entry.append(
(getattr(r, k).table(),
getattr(getattr(r, k), 'notes', lambda: [])())
if getattr(r, k, None) is not None
else types[k].none)
elif percent:
# compare entry?
elif compare is not None and diff_results is None:
for k in fields:
entry.append(
(getattr(r, k).table()
if getattr(r, k, None) is not None
else types[k].none,
(lambda t: ['+∞%'] if t == +mt.inf
else ['-∞%'] if t == -mt.inf
else ['%+.1f%%' % (100*t)])(
types[k].ratio(
getattr(r, k, None),
getattr(compare_result, k, None)))))
# percent entry?
elif diff_results is not None and percent:
for k in fields:
entry.append(
(getattr(r, k).table()
@@ -791,7 +822,8 @@ def table(Result, results, diff_results=None, *,
types[k].ratio(
getattr(r, k, None),
getattr(diff_r, k, None)))))
else:
# diff entry?
elif diff_results is not None:
for k in fields:
entry.append(getattr(diff_r, k).table()
if getattr(diff_r, k, None) is not None
@@ -887,7 +919,8 @@ def table(Result, results, diff_results=None, *,
"| ",
" "))
# total
# total, unless we're comparing
if summary or not (compare is not None and diff_results is None):
r = next(iter(fold(Result, results, by=[])), None)
if diff_results is None:
diff_r = None
@@ -1200,6 +1233,10 @@ if __name__ == "__main__":
'-p', '--percent',
action='store_true',
help="Only show percentage change, not a full diff.")
parser.add_argument(
'-c', '--compare',
type=lambda x: tuple(v.strip() for v in x.split(',')),
help="Compare results to the row matching this by pattern.")
parser.add_argument(
'-b', '--by',
action='append',

View File

@@ -340,6 +340,7 @@ def table(Result, results, diff_results=None, *,
summary=False,
all=False,
percent=False,
compare=None,
depth=None,
hot=None,
**_):
@@ -401,8 +402,22 @@ def table(Result, results, diff_results=None, *,
getattr(diff_table.get(name), k, None))
for k in fields)]
# find compare entry if there is one
if compare is not None:
compare_result = table.get(','.join(str(k) for k in compare))
# sort again, now with diff info, note that python's sort is stable
names.sort()
if compare is not None:
names.sort(
key=lambda n: (
table.get(n) == compare_result,
tuple(
types[k].ratio(
getattr(table.get(n), k, None),
getattr(compare_result, k, None))
for k in fields)),
reverse=True)
if diff_results is not None:
names.sort(
key=lambda n: tuple(
@@ -454,14 +469,30 @@ def table(Result, results, diff_results=None, *,
# entry helper
def table_entry(name, r, diff_r=None):
entry = [name]
if diff_results is None:
# normal entry?
if ((compare is None or r == compare_result)
and diff_results is None):
for k in fields:
entry.append(
(getattr(r, k).table(),
getattr(getattr(r, k), 'notes', lambda: [])())
if getattr(r, k, None) is not None
else types[k].none)
elif percent:
# compare entry?
elif compare is not None and diff_results is None:
for k in fields:
entry.append(
(getattr(r, k).table()
if getattr(r, k, None) is not None
else types[k].none,
(lambda t: ['+∞%'] if t == +mt.inf
else ['-∞%'] if t == -mt.inf
else ['%+.1f%%' % (100*t)])(
types[k].ratio(
getattr(r, k, None),
getattr(compare_result, k, None)))))
# percent entry?
elif diff_results is not None and percent:
for k in fields:
entry.append(
(getattr(r, k).table()
@@ -473,7 +504,8 @@ def table(Result, results, diff_results=None, *,
types[k].ratio(
getattr(r, k, None),
getattr(diff_r, k, None)))))
else:
# diff entry?
elif diff_results is not None:
for k in fields:
entry.append(getattr(diff_r, k).table()
if getattr(diff_r, k, None) is not None
@@ -569,7 +601,8 @@ def table(Result, results, diff_results=None, *,
"| ",
" "))
# total
# total, unless we're comparing
if summary or not (compare is not None and diff_results is None):
r = next(iter(fold(Result, results, by=[])), None)
if diff_results is None:
diff_r = None
@@ -745,6 +778,10 @@ if __name__ == "__main__":
'-p', '--percent',
action='store_true',
help="Only show percentage change, not a full diff.")
parser.add_argument(
'-c', '--compare',
type=lambda x: tuple(v.strip() for v in x.split(',')),
help="Compare results to the row matching this by pattern.")
parser.add_argument(
'-b', '--by',
action='append',

View File

@@ -328,6 +328,7 @@ def table(Result, results, diff_results=None, *,
summary=False,
all=False,
percent=False,
compare=None,
**_):
all_, all = all, __builtins__.all
@@ -359,8 +360,22 @@ def table(Result, results, diff_results=None, *,
getattr(diff_table.get(name), k, None))
for k in fields)]
# find compare entry if there is one
if compare is not None:
compare_result = table.get(','.join(str(k) for k in compare))
# sort again, now with diff info, note that python's sort is stable
names.sort()
if compare is not None:
names.sort(
key=lambda n: (
table.get(n) == compare_result,
tuple(
types[k].ratio(
getattr(table.get(n), k, None),
getattr(compare_result, k, None))
for k in fields)),
reverse=True)
if diff_results is not None:
names.sort(
key=lambda n: tuple(
@@ -412,14 +427,30 @@ def table(Result, results, diff_results=None, *,
# entry helper
def table_entry(name, r, diff_r=None):
entry = [name]
if diff_results is None:
# normal entry?
if ((compare is None or r == compare_result)
and diff_results is None):
for k in fields:
entry.append(
(getattr(r, k).table(),
getattr(getattr(r, k), 'notes', lambda: [])())
if getattr(r, k, None) is not None
else types[k].none)
elif percent:
# compare entry?
elif compare is not None and diff_results is None:
for k in fields:
entry.append(
(getattr(r, k).table()
if getattr(r, k, None) is not None
else types[k].none,
(lambda t: ['+∞%'] if t == +mt.inf
else ['-∞%'] if t == -mt.inf
else ['%+.1f%%' % (100*t)])(
types[k].ratio(
getattr(r, k, None),
getattr(compare_result, k, None)))))
# percent entry?
elif diff_results is not None and percent:
for k in fields:
entry.append(
(getattr(r, k).table()
@@ -431,7 +462,8 @@ def table(Result, results, diff_results=None, *,
types[k].ratio(
getattr(r, k, None),
getattr(diff_r, k, None)))))
else:
# diff entry?
elif diff_results is not None:
for k in fields:
entry.append(getattr(diff_r, k).table()
if getattr(diff_r, k, None) is not None
@@ -464,7 +496,8 @@ def table(Result, results, diff_results=None, *,
diff_r = diff_table.get(name)
lines.append(table_entry(name, r, diff_r))
# total
# total, unless we're comparing
if summary or not (compare is not None and diff_results is None):
r = next(iter(fold(Result, results, by=[])), None)
if diff_results is None:
diff_r = None
@@ -631,6 +664,10 @@ if __name__ == "__main__":
'-p', '--percent',
action='store_true',
help="Only show percentage change, not a full diff.")
parser.add_argument(
'-c', '--compare',
type=lambda x: tuple(v.strip() for v in x.split(',')),
help="Compare results to the row matching this by pattern.")
parser.add_argument(
'-b', '--by',
action='append',