diff --git a/util/size-experiment.py b/util/size-experiment.py new file mode 100644 index 000000000..8acacf9d1 --- /dev/null +++ b/util/size-experiment.py @@ -0,0 +1,90 @@ +import subprocess +from itertools import product +import shutil +import os +from collections import defaultdict +from pprint import pprint + +# Set to false if you've only changed the analysis and do not want to recompile +# the binaries. +RECOMPILE = True + +STRIP_VALS = ["none", "debuginfo", "symbols"] +PANIC_VALS = ["unwind", "abort"] +OPT_LEVEL_VALS = [3, "s", "z"] +LTO_VALS = ["off", "thin", "fat"] + + +def config(name, val): + return ["--config", f"profile.release.{name}={val!r}"] + + +sizes = {} + +for (strip, panic, opt, lto) in product( + STRIP_VALS, PANIC_VALS, OPT_LEVEL_VALS, LTO_VALS +): + if RECOMPILE: + cmd = [ + "cargo", + "build", + "--release", + "--features=unix", + *config("strip", strip), + *config("panic", panic), + *config("opt-level", opt), + *config("lto", lto), + ] + print("RUN:", " ".join(cmd)) + res = subprocess.call(cmd) + + shutil.copyfile( + "target/release/coreutils", + "-".join(["coreutils", strip, panic, str(opt), lto]), + ) + print(res) + + sizes[(strip, panic, opt, lto)] = os.path.getsize( + "-".join(["coreutils", strip, panic, str(opt), lto]) + ) + +changes_absolute = defaultdict(list) +changes_percent = defaultdict(list) + + +def with_val_at_idx(val, idx, other): + other = list(other) + other.insert(idx, val) + return tuple(other) + + +def collect_diff(idx, name): + all_params = [STRIP_VALS, PANIC_VALS, OPT_LEVEL_VALS, LTO_VALS] + vals = all_params.pop(idx) + for other in product(*all_params): + baseline = sizes[with_val_at_idx(vals[0], idx, other)] + for val in vals[1:]: + changes = sizes[with_val_at_idx(val, idx, other)] - baseline + changes_absolute[f"{name}={val}"].append(changes) + changes_percent[f"{name}={val}"].append(changes / baseline * 100) + + +collect_diff(0, "strip") +collect_diff(1, "panic") +collect_diff(2, "opt-level") +collect_diff(3, "lto") + + +def analyze(l): + return f"MIN: {float(min(l)):.3}, AVG: {float(sum(l)/len(l)):.3}, MAX: {float(max(l)):.3}" + + +print("Absolute changes") +pprint({k: analyze(v) for k, v in changes_absolute.items()}) +print() +print("Percent changes") +pprint({k: analyze(v) for k, v in changes_percent.items()}) + +print() +print(changes_percent["opt-level=s"]) +print(changes_percent["opt-level=z"])