all repos

clerk @ 17c786e0f3f26481a635695160d516a7039a3bef

missing tooling for ledger/hledger

clerk/.github/scripts/check-bench-regression.py (view raw)

Oleksandr Smirnov Oleksandr Smirnov
olexsmir@gmail.com
ci: stabilize benchmark regression check..., 1 month ago
1
#!/usr/bin/env python3
2
"""Fail if any benchmark regressed beyond the threshold.
3
4
Reads benchstat CSV comparison (old vs new) from stdin. benchstat only
5
reports a numeric delta for statistically significant changes (p < 0.05);
6
noisy comparisons are marked "~" and ignored.
7
Only sec/op rows are judged; B/op and allocs/op deltas are informational
8
(deliberate tradeoffs like buffering input shift memory without slowing
9
down).
10
"""
11
import csv
12
import sys
13
14
THRESHOLD = 20.0  # percent slower
15
16
def delta_pct(s):
17
    s = s.strip()
18
    if not s or s == "~":
19
        return None
20
    sign = 1.0
21
    if s.startswith("+"):
22
        s = s[1:]
23
    elif s.startswith("-"):
24
        sign = -1.0
25
        s = s[1:]
26
    s = s.rstrip("%")
27
    if s in ("∞", "Inf", "inf", "+Inf"):
28
        return sign * float("inf")
29
    try:
30
        return sign * float(s)
31
    except ValueError:
32
        return None
33
34
def main():
35
    regressions = []
36
    unit = ""
37
    for row in csv.reader(sys.stdin):
38
        if row and row[0] == "":
39
            unit = row[1] if len(row) > 1 else ""
40
            continue
41
        if len(row) < 7 or row[0] in ("geomean",):
42
            continue
43
        if unit != "sec/op":
44
            continue
45
        d = delta_pct(row[5])  # vs base column
46
        if d is not None and d > THRESHOLD:
47
            regressions.append((row[0], d))
48
49
    if not regressions:
50
        print("no regressions beyond +%.0f%%" % THRESHOLD)
51
        return 0
52
53
    print("performance regressions beyond +%.0f%%:" % THRESHOLD)
54
    for name, d in sorted(regressions):
55
        if d == float("inf"):
56
            print("  %s: +∞ (new cost where none before)" % name)
57
        else:
58
            print("  %s: +%.1f%%" % (name, d))
59
    return 1
60
61
62
if __name__ == "__main__":
63
    sys.exit(main())