Skip to content

Instantly share code, notes, and snippets.

@brandonchinn178
Last active February 17, 2024 07:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brandonchinn178/75ebf64c81f3a19dd46e06783ef585a9 to your computer and use it in GitHub Desktop.
Save brandonchinn178/75ebf64c81f3a19dd46e06783ef585a9 to your computer and use it in GitHub Desktop.
Build with the following command:
```bash
hadrian/build -j9 --freeze1
```
Then
```
GHC=/path/to/repo/_build/stage1/bin/ghc ./run.py
```
Note: `--flavour=perf` and `--flavour=bench` weren't working for me on my M2 Mac.
Errors about `StgWord` being `unsigned long long` or "build rule finished but
rts-something.dylib not built"
#!/usr/bin/env python3
from __future__ import annotations
import os
import string
import subprocess
import timeit
from pathlib import Path
HERE = Path(__file__).resolve().parent
GHC = Path(os.environ["GHC"])
NUM_ITERATIONS = 30
def show_str(s: str, *, escape: bool = True) -> str:
if escape:
s = s.replace("\\", "\\\\").replace('"', '\\"')
return '"' + s + '"'
def show_char(c: str, *, escape: bool = True) -> str:
if escape:
c = c.replace("\\", "\\\\").replace("'", "\\'")
return "'" + c + "'"
VALID_CHARS = string.ascii_letters + string.digits + string.punctuation + " "
STR = VALID_CHARS
ESCAPE_CHARS = [
"\\\\",
"\\a",
"\\b",
"\\f",
"\\n",
"\\r",
"\\t",
"\\v",
"\\\\",
'\\"',
"\\'",
"\\NUL",
"\\SOH",
"\\STX",
"\\ETX",
"\\EOT",
"\\ENQ",
"\\ACK",
"\\BEL",
"\\BS",
"\\HT",
"\\LF",
"\\VT",
"\\FF",
"\\CR",
"\\SO",
"\\SI",
"\\DLE",
"\\DC1",
"\\DC2",
"\\DC3",
"\\DC4",
"\\NAK",
"\\SYN",
"\\ETB",
"\\CAN",
"\\EM",
"\\SUB",
"\\ESC",
"\\FS",
"\\GS",
"\\RS",
"\\US",
"\\SP",
"\\DEL",
"\\xa8bd",
"\\o111",
"\\189",
]
class Bench:
def get_vals(self) -> list[str]:
raise NotImplemented
def run(self):
name = self.__class__.__name__
testdir = HERE / name
testdir.mkdir(parents=True, exist_ok=True)
program = "main = {}".format(
" >> ".join(
f'print {s}'
for s in self.get_vals()
)
)
input_file = testdir / "input.hs"
input_file.write_text(program)
def compile():
p = subprocess.run(
[GHC, input_file],
capture_output=True,
cwd=testdir,
)
if p.returncode != 0:
stderr = p.stderr.decode()
n = 1000
raise Exception(stderr[:n] + "[...]" + stderr[-n:])
print(f"=====> {name}")
duration = timeit.timeit(compile, number=NUM_ITERATIONS)
print(f"Average: {duration / NUM_ITERATIONS} secs")
print("")
class BenchLongString(Bench):
def get_vals(self) -> list[str]:
return [show_str(STR * 10000)]
class BenchManyStrings(Bench):
def get_vals(self) -> list[str]:
return [show_str(STR) for _ in range(10000)]
class BenchLongEscapeString(Bench):
def get_vals(self) -> list[str]:
return [show_str("".join(ESCAPE_CHARS) * 1000, escape=False)]
class BenchManyChars(Bench):
def get_vals(self) -> list[str]:
return [show_char(c) for c in VALID_CHARS] * 100
class BenchManyEscapeChars(Bench):
def get_vals(self) -> list[str]:
return [show_char(c, escape=False) for c in ESCAPE_CHARS] * 1000
if __name__ == "__main__":
print(f"Running benchmarks against: {GHC}")
print("")
BenchLongString().run()
BenchManyStrings().run()
BenchLongEscapeString().run()
BenchManyChars().run()
BenchManyEscapeChars().run()
Running benchmarks against: /Users/bchinn/repos/ghc/_build/stage1/bin/ghc
=====> BenchLongString
Average: 0.091564694433085 secs
=====> BenchManyStrings
Average: 0.09195360000012442 secs
=====> BenchLongEscapeString
Average: 0.09198539306526073 secs
=====> BenchManyChars
Average: 0.09180612780037337 secs
=====> BenchManyEscapeChars
Average: 0.09192637363254713 secs
Running benchmarks against: /Users/bchinn/repos/ghc/_build/stage1/bin/ghc
=====> BenchLongString
Average: 0.09138900000058735 secs
=====> BenchManyStrings
Average: 0.09150341526643994 secs
=====> BenchLongEscapeString
Average: 0.09167130139928001 secs
=====> BenchManyChars
Average: 0.09189670833487375 secs
=====> BenchManyEscapeChars
Average: 0.09206391806559017 secs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment