107 lines
3.6 KiB
Python
107 lines
3.6 KiB
Python
"""
|
|
A benchmark suite for Performance Anti-Patterns
|
|
"""
|
|
import timeit
|
|
import pathlib
|
|
import sys
|
|
from statistics import fmean
|
|
from rich.console import Console
|
|
from rich.table import Table
|
|
from rich.text import Text
|
|
|
|
REPEAT = 5
|
|
TIMES = 5
|
|
|
|
|
|
def format_delta(result: float, comparator: float, delta: float) -> Text:
|
|
"""
|
|
Color the column a shade of green if the result was faster than the comparator,
|
|
red if it was slower, and format the string appropriately with %, minus symbol, etc.
|
|
"""
|
|
minus = ""
|
|
if abs(delta) > 100:
|
|
formatter = "{0:.5f} ({1}{2:.1f}%)"
|
|
else:
|
|
formatter = "{0:.7f} ({1}{2:.1f}%)"
|
|
if result < comparator:
|
|
if delta < 10:
|
|
col = "medium_spring_green"
|
|
elif 10 <= delta < 20:
|
|
col = "spring_green1"
|
|
elif 20 <= delta < 40:
|
|
col = "spring_green2"
|
|
else:
|
|
col = "green1"
|
|
return Text(formatter.format(result, minus, delta), style=col)
|
|
else:
|
|
minus = "-"
|
|
return Text(formatter.format(result, minus, delta), style="red")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
table = Table(
|
|
title=f"Anti-Pattern Benchmark Suite, repeat={REPEAT}, number={TIMES}"
|
|
)
|
|
|
|
table.add_column("Benchmark", justify="right", style="cyan", no_wrap=True)
|
|
table.add_column("Min", width=10)
|
|
table.add_column("Max", width=10)
|
|
table.add_column("Mean", width=10)
|
|
table.add_column("Min (+)", style="blue", width=21)
|
|
table.add_column("Max (+)", style="blue", width=21)
|
|
table.add_column("Mean (+)", style="blue", width=21)
|
|
|
|
profiles_out = pathlib.Path(__file__).parent / "profiles"
|
|
if not profiles_out.exists():
|
|
profiles_out.mkdir()
|
|
n = 0
|
|
|
|
for f in pathlib.Path(__file__).parent.glob("bench_*.py"):
|
|
if len(sys.argv) > 1 and f.stem != f"bench_{sys.argv[1]}":
|
|
continue
|
|
i = __import__(
|
|
f.stem,
|
|
globals(),
|
|
locals(),
|
|
)
|
|
if hasattr(i, "__benchmarks__"):
|
|
for benchmark in i.__benchmarks__:
|
|
n += 1
|
|
func1, func2, desc = benchmark
|
|
comparator_result = timeit.repeat(func1, repeat=REPEAT, number=TIMES)
|
|
result = timeit.repeat(func2, repeat=REPEAT, number=TIMES)
|
|
|
|
delta_mean = (
|
|
abs(fmean(result) - fmean(comparator_result))
|
|
/ fmean(comparator_result)
|
|
) * 100.0
|
|
delta_min = (
|
|
abs(min(result) - min(comparator_result)) / min(comparator_result)
|
|
) * 100.0
|
|
delta_max = (
|
|
abs(max(result) - max(comparator_result)) / max(comparator_result)
|
|
) * 100.0
|
|
|
|
fdelta_min = format_delta(
|
|
min(result), min(comparator_result), delta_min
|
|
)
|
|
fdelta_max = format_delta(
|
|
max(result), max(comparator_result), delta_max
|
|
)
|
|
fdelta_mean = format_delta(
|
|
fmean(result), fmean(comparator_result), delta_mean
|
|
)
|
|
|
|
table.add_row(
|
|
desc,
|
|
"{:.7f}".format(min(comparator_result)),
|
|
"{:.7f}".format(max(comparator_result)),
|
|
"{:.7f}".format(fmean(comparator_result)),
|
|
fdelta_min,
|
|
fdelta_max,
|
|
fdelta_mean,
|
|
)
|
|
|
|
console = Console(width=150)
|
|
console.print(table)
|