diff --git a/.gitignore b/.gitignore index 5c4aa939..8dcc9371 100644 --- a/.gitignore +++ b/.gitignore @@ -135,3 +135,8 @@ benchmarks/cases/**/*.o /test_output.txt /test_stale_reason.txt /osprey_http_state_levels.db +# `osprey test ` runs each program from its own directory, so the same two +# files also land beside the test. Fully anchored for the reason above: these +# exact paths, never a bare name that could hide a real fixture elsewhere. +/tests/regressions/basics/files/test_output.txt +/tests/regressions/basics/files/test_stale_reason.txt diff --git a/benchmarks/README.md b/benchmarks/README.md index 7ac0b136..435929c0 100644 --- a/benchmarks/README.md +++ b/benchmarks/README.md @@ -28,7 +28,7 @@ zsh benchmarks/run.sh primes # direct, single case > column on a machine with a few GB free, or skip it with `BENCH_FILTER`. > > -> Current measured peaks: default **2.53 GB**, `--memory=arc` **2.98 MB**, and `--memory=gc` **19.1 MB**. +> Current measured peaks: default **1.9 GB**, `--memory=arc` **3.03 MB**, and `--memory=gc` **21.3 MB**. > Results are written to `benchmarks/results/`. The measured outputs below are diff --git a/benchmarks/results/raw.jsonl b/benchmarks/results/raw.jsonl index 58fe5312..9116d800 100644 --- a/benchmarks/results/raw.jsonl +++ b/benchmarks/results/raw.jsonl @@ -1,220 +1,242 @@ -{"case":"ackermann","lang":"rust","status":"ok","output":"8189","expected":"8189","rss":1835008} -{"case":"ackermann","lang":"c","status":"ok","output":"8189","expected":"8189","rss":1687552} -{"case":"ackermann","lang":"csharp","status":"ok","output":"8189","expected":"8189","rss":7340032} -{"case":"ackermann","lang":"dart","status":"ok","output":"8189","expected":"8189","rss":14696448} -{"case":"ackermann","lang":"ocaml","status":"ok","output":"8189","expected":"8189","rss":2752512} -{"case":"ackermann","lang":"haskell","status":"ok","output":"8189","expected":"8189","rss":15826944} +{"case":"ackermann","lang":"osprey","status":"ok","output":"8189","expected":"8189","rss":2064384} +{"case":"ackermann","lang":"osprey-arc","status":"ok","output":"8189","expected":"8189","rss":2080768} +{"case":"ackermann","lang":"osprey-gc","status":"ok","output":"8189","expected":"8189","rss":22036480} +{"case":"ackermann","lang":"rust","status":"ok","output":"8189","expected":"8189","rss":1884160} +{"case":"ackermann","lang":"c","status":"ok","output":"8189","expected":"8189","rss":1736704} +{"case":"ackermann","lang":"csharp","status":"ok","output":"8189","expected":"8189","rss":7421952} +{"case":"ackermann","lang":"dart","status":"ok","output":"8189","expected":"8189","rss":14729216} +{"case":"ackermann","lang":"ocaml","status":"ok","output":"8189","expected":"8189","rss":2801664} +{"case":"ackermann","lang":"haskell","status":"ok","output":"8189","expected":"8189","rss":15876096} +{"case":"ackermann","lang":"osprey-wasm","status":"wrong_output","output":"","expected":"8189","rss":0} {"case":"ackermann","lang":"rust-wasm","status":"ok","output":"8189","expected":"8189","rss":0} -{"case":"binarytrees","lang":"rust","status":"ok","output":"19659600","expected":"19659600","rss":2211840} -{"case":"binarytrees","lang":"c","status":"ok","output":"19659600","expected":"19659600","rss":1753088} -{"case":"binarytrees","lang":"csharp","status":"ok","output":"19659600","expected":"19659600","rss":16859136} -{"case":"binarytrees","lang":"dart","status":"ok","output":"19659600","expected":"19659600","rss":23543808} -{"case":"binarytrees","lang":"ocaml","status":"ok","output":"19659600","expected":"19659600","rss":5373952} -{"case":"binarytrees","lang":"haskell","status":"ok","output":"19659600","expected":"19659600","rss":11550720} +{"case":"binarytrees","lang":"osprey","status":"ok","output":"19659600","expected":"19659600","rss":1896349696} +{"case":"binarytrees","lang":"osprey-arc","status":"ok","output":"19659600","expected":"19659600","rss":3031040} +{"case":"binarytrees","lang":"osprey-gc","status":"ok","output":"19659600","expected":"19659600","rss":21282816} +{"case":"binarytrees","lang":"rust","status":"ok","output":"19659600","expected":"19659600","rss":2293760} +{"case":"binarytrees","lang":"c","status":"ok","output":"19659600","expected":"19659600","rss":1835008} +{"case":"binarytrees","lang":"csharp","status":"ok","output":"19659600","expected":"19659600","rss":16891904} +{"case":"binarytrees","lang":"dart","status":"ok","output":"19659600","expected":"19659600","rss":23560192} +{"case":"binarytrees","lang":"ocaml","status":"ok","output":"19659600","expected":"19659600","rss":5423104} +{"case":"binarytrees","lang":"haskell","status":"ok","output":"19659600","expected":"19659600","rss":11599872} +{"case":"binarytrees","lang":"osprey-wasm","status":"ok","output":"19659600","expected":"19659600","rss":0} {"case":"binarytrees","lang":"rust-wasm","status":"ok","output":"19659600","expected":"19659600","rss":0} -{"case":"coins","lang":"rust","status":"ok","output":"116727","expected":"116727","rss":1589248} -{"case":"coins","lang":"c","status":"ok","output":"116727","expected":"116727","rss":1474560} -{"case":"coins","lang":"csharp","status":"ok","output":"116727","expected":"116727","rss":7143424} -{"case":"coins","lang":"dart","status":"ok","output":"116727","expected":"116727","rss":14581760} -{"case":"coins","lang":"ocaml","status":"ok","output":"116727","expected":"116727","rss":2326528} -{"case":"coins","lang":"haskell","status":"ok","output":"116727","expected":"116727","rss":11616256} +{"case":"coins","lang":"osprey","status":"ok","output":"116727","expected":"116727","rss":1572864} +{"case":"coins","lang":"osprey-arc","status":"ok","output":"116727","expected":"116727","rss":1589248} +{"case":"coins","lang":"osprey-gc","status":"ok","output":"116727","expected":"116727","rss":21544960} +{"case":"coins","lang":"rust","status":"ok","output":"116727","expected":"116727","rss":1638400} +{"case":"coins","lang":"c","status":"ok","output":"116727","expected":"116727","rss":1523712} +{"case":"coins","lang":"csharp","status":"ok","output":"116727","expected":"116727","rss":7176192} +{"case":"coins","lang":"dart","status":"ok","output":"116727","expected":"116727","rss":14598144} +{"case":"coins","lang":"ocaml","status":"ok","output":"116727","expected":"116727","rss":2375680} +{"case":"coins","lang":"haskell","status":"ok","output":"116727","expected":"116727","rss":11665408} +{"case":"coins","lang":"osprey-wasm","status":"ok","output":"116727","expected":"116727","rss":0} {"case":"coins","lang":"rust-wasm","status":"ok","output":"116727","expected":"116727","rss":0} -{"case":"collatz","lang":"rust","status":"ok","output":"10753840","expected":"10753840","rss":1605632} -{"case":"collatz","lang":"c","status":"ok","output":"10753840","expected":"10753840","rss":1441792} -{"case":"collatz","lang":"csharp","status":"ok","output":"10753840","expected":"10753840","rss":7159808} -{"case":"collatz","lang":"dart","status":"ok","output":"10753840","expected":"10753840","rss":14581760} -{"case":"collatz","lang":"ocaml","status":"ok","output":"10753840","expected":"10753840","rss":2310144} -{"case":"collatz","lang":"haskell","status":"ok","output":"10753840","expected":"10753840","rss":11616256} +{"case":"collatz","lang":"osprey","status":"ok","output":"10753840","expected":"10753840","rss":232554496} +{"case":"collatz","lang":"osprey-arc","status":"ok","output":"10753840","expected":"10753840","rss":1605632} +{"case":"collatz","lang":"osprey-gc","status":"ok","output":"10753840","expected":"10753840","rss":19415040} +{"case":"collatz","lang":"rust","status":"ok","output":"10753840","expected":"10753840","rss":1654784} +{"case":"collatz","lang":"c","status":"ok","output":"10753840","expected":"10753840","rss":1490944} +{"case":"collatz","lang":"csharp","status":"ok","output":"10753840","expected":"10753840","rss":7225344} +{"case":"collatz","lang":"dart","status":"ok","output":"10753840","expected":"10753840","rss":14712832} +{"case":"collatz","lang":"ocaml","status":"ok","output":"10753840","expected":"10753840","rss":2375680} +{"case":"collatz","lang":"haskell","status":"ok","output":"10753840","expected":"10753840","rss":11681792} +{"case":"collatz","lang":"osprey-wasm","status":"ok","output":"10753840","expected":"10753840","rss":0} {"case":"collatz","lang":"rust-wasm","status":"ok","output":"10753840","expected":"10753840","rss":0} -{"case":"coprime","lang":"rust","status":"ok","output":"2433175","expected":"2433175","rss":1589248} -{"case":"coprime","lang":"c","status":"ok","output":"2433175","expected":"2433175","rss":1458176} -{"case":"coprime","lang":"csharp","status":"ok","output":"2433175","expected":"2433175","rss":7159808} -{"case":"coprime","lang":"dart","status":"ok","output":"2433175","expected":"2433175","rss":14548992} -{"case":"coprime","lang":"ocaml","status":"ok","output":"2433175","expected":"2433175","rss":2326528} -{"case":"coprime","lang":"haskell","status":"ok","output":"2433175","expected":"2433175","rss":11616256} +{"case":"coprime","lang":"osprey","status":"ok","output":"2433175","expected":"2433175","rss":1540096} +{"case":"coprime","lang":"osprey-arc","status":"ok","output":"2433175","expected":"2433175","rss":1605632} +{"case":"coprime","lang":"osprey-gc","status":"ok","output":"2433175","expected":"2433175","rss":19562496} +{"case":"coprime","lang":"rust","status":"ok","output":"2433175","expected":"2433175","rss":1638400} +{"case":"coprime","lang":"c","status":"ok","output":"2433175","expected":"2433175","rss":1507328} +{"case":"coprime","lang":"csharp","status":"ok","output":"2433175","expected":"2433175","rss":7176192} +{"case":"coprime","lang":"dart","status":"ok","output":"2433175","expected":"2433175","rss":14647296} +{"case":"coprime","lang":"ocaml","status":"ok","output":"2433175","expected":"2433175","rss":2375680} +{"case":"coprime","lang":"haskell","status":"ok","output":"2433175","expected":"2433175","rss":11681792} +{"case":"coprime","lang":"osprey-wasm","status":"ok","output":"2433175","expected":"2433175","rss":0} {"case":"coprime","lang":"rust-wasm","status":"ok","output":"2433175","expected":"2433175","rss":0} -{"case":"digitsum","lang":"rust","status":"ok","output":"55000002","expected":"55000002","rss":1605632} -{"case":"digitsum","lang":"c","status":"ok","output":"55000002","expected":"55000002","rss":1458176} -{"case":"digitsum","lang":"csharp","status":"ok","output":"55000002","expected":"55000002","rss":7143424} -{"case":"digitsum","lang":"dart","status":"ok","output":"55000002","expected":"55000002","rss":14548992} -{"case":"digitsum","lang":"ocaml","status":"ok","output":"55000002","expected":"55000002","rss":2326528} -{"case":"digitsum","lang":"haskell","status":"ok","output":"55000002","expected":"55000002","rss":11599872} +{"case":"digitsum","lang":"osprey","status":"ok","output":"55000002","expected":"55000002","rss":351404032} +{"case":"digitsum","lang":"osprey-arc","status":"ok","output":"55000002","expected":"55000002","rss":1589248} +{"case":"digitsum","lang":"osprey-gc","status":"ok","output":"55000002","expected":"55000002","rss":23117824} +{"case":"digitsum","lang":"rust","status":"ok","output":"55000002","expected":"55000002","rss":1654784} +{"case":"digitsum","lang":"c","status":"ok","output":"55000002","expected":"55000002","rss":1507328} +{"case":"digitsum","lang":"csharp","status":"ok","output":"55000002","expected":"55000002","rss":7192576} +{"case":"digitsum","lang":"dart","status":"ok","output":"55000002","expected":"55000002","rss":14647296} +{"case":"digitsum","lang":"ocaml","status":"ok","output":"55000002","expected":"55000002","rss":2375680} +{"case":"digitsum","lang":"haskell","status":"ok","output":"55000002","expected":"55000002","rss":11665408} +{"case":"digitsum","lang":"osprey-wasm","status":"ok","output":"55000002","expected":"55000002","rss":0} {"case":"digitsum","lang":"rust-wasm","status":"ok","output":"55000002","expected":"55000002","rss":0} -{"case":"exprtree","lang":"rust","status":"ok","output":"900720437","expected":"900720437","rss":2768896} -{"case":"exprtree","lang":"c","status":"ok","output":"900720437","expected":"900720437","rss":11993088} -{"case":"exprtree","lang":"csharp","status":"ok","output":"900720437","expected":"900720437","rss":15925248} -{"case":"exprtree","lang":"dart","status":"ok","output":"900720437","expected":"900720437","rss":23560192} -{"case":"exprtree","lang":"ocaml","status":"ok","output":"900720437","expected":"900720437","rss":6340608} -{"case":"exprtree","lang":"haskell","status":"ok","output":"900720437","expected":"900720437","rss":11894784} +{"case":"exprtree","lang":"osprey","status":"ok","output":"900720437","expected":"900720437","rss":9551872} +{"case":"exprtree","lang":"osprey-arc","status":"ok","output":"900720437","expected":"900720437","rss":3588096} +{"case":"exprtree","lang":"osprey-gc","status":"ok","output":"900720437","expected":"900720437","rss":19431424} +{"case":"exprtree","lang":"rust","status":"ok","output":"900720437","expected":"900720437","rss":2801664} +{"case":"exprtree","lang":"c","status":"ok","output":"900720437","expected":"900720437","rss":12042240} +{"case":"exprtree","lang":"csharp","status":"ok","output":"900720437","expected":"900720437","rss":15958016} +{"case":"exprtree","lang":"dart","status":"ok","output":"900720437","expected":"900720437","rss":23625728} +{"case":"exprtree","lang":"ocaml","status":"ok","output":"900720437","expected":"900720437","rss":6389760} +{"case":"exprtree","lang":"haskell","status":"ok","output":"900720437","expected":"900720437","rss":11943936} +{"case":"exprtree","lang":"osprey-wasm","status":"ok","output":"900720437","expected":"900720437","rss":0} {"case":"exprtree","lang":"rust-wasm","status":"ok","output":"900720437","expected":"900720437","rss":0} -{"case":"factorial","lang":"rust","status":"ok","output":"682498929","expected":"682498929","rss":1605632} -{"case":"factorial","lang":"c","status":"ok","output":"682498929","expected":"682498929","rss":1441792} +{"case":"factorial","lang":"osprey","status":"ok","output":"682498929","expected":"682498929","rss":1540096} +{"case":"factorial","lang":"osprey-arc","status":"ok","output":"682498929","expected":"682498929","rss":1572864} +{"case":"factorial","lang":"osprey-gc","status":"ok","output":"682498929","expected":"682498929","rss":1572864} +{"case":"factorial","lang":"rust","status":"ok","output":"682498929","expected":"682498929","rss":1654784} +{"case":"factorial","lang":"c","status":"ok","output":"682498929","expected":"682498929","rss":1490944} {"case":"factorial","lang":"csharp","status":"ok","output":"682498929","expected":"682498929","rss":7159808} -{"case":"factorial","lang":"dart","status":"ok","output":"682498929","expected":"682498929","rss":14499840} -{"case":"factorial","lang":"ocaml","status":"ok","output":"682498929","expected":"682498929","rss":2310144} -{"case":"factorial","lang":"haskell","status":"ok","output":"682498929","expected":"682498929","rss":11632640} +{"case":"factorial","lang":"dart","status":"ok","output":"682498929","expected":"682498929","rss":14565376} +{"case":"factorial","lang":"ocaml","status":"ok","output":"682498929","expected":"682498929","rss":2392064} +{"case":"factorial","lang":"haskell","status":"ok","output":"682498929","expected":"682498929","rss":11681792} +{"case":"factorial","lang":"osprey-wasm","status":"ok","output":"682498929","expected":"682498929","rss":0} {"case":"factorial","lang":"rust-wasm","status":"ok","output":"682498929","expected":"682498929","rss":0} -{"case":"fib","lang":"rust","status":"ok","output":"9227465","expected":"9227465","rss":1605632} -{"case":"fib","lang":"c","status":"ok","output":"9227465","expected":"9227465","rss":1441792} -{"case":"fib","lang":"csharp","status":"ok","output":"9227465","expected":"9227465","rss":7159808} -{"case":"fib","lang":"dart","status":"ok","output":"9227465","expected":"9227465","rss":14532608} -{"case":"fib","lang":"ocaml","status":"ok","output":"9227465","expected":"9227465","rss":2326528} -{"case":"fib","lang":"haskell","status":"ok","output":"9227465","expected":"9227465","rss":11632640} +{"case":"fib","lang":"osprey","status":"ok","output":"9227465","expected":"9227465","rss":1572864} +{"case":"fib","lang":"osprey-arc","status":"ok","output":"9227465","expected":"9227465","rss":1605632} +{"case":"fib","lang":"osprey-gc","status":"ok","output":"9227465","expected":"9227465","rss":23527424} +{"case":"fib","lang":"rust","status":"ok","output":"9227465","expected":"9227465","rss":1654784} +{"case":"fib","lang":"c","status":"ok","output":"9227465","expected":"9227465","rss":1490944} +{"case":"fib","lang":"csharp","status":"ok","output":"9227465","expected":"9227465","rss":7176192} +{"case":"fib","lang":"dart","status":"ok","output":"9227465","expected":"9227465","rss":14598144} +{"case":"fib","lang":"ocaml","status":"ok","output":"9227465","expected":"9227465","rss":2359296} +{"case":"fib","lang":"haskell","status":"ok","output":"9227465","expected":"9227465","rss":11698176} +{"case":"fib","lang":"osprey-wasm","status":"ok","output":"9227465","expected":"9227465","rss":0} {"case":"fib","lang":"rust-wasm","status":"ok","output":"9227465","expected":"9227465","rss":0} -{"case":"gcdsum","lang":"rust","status":"ok","output":"7201567","expected":"7201567","rss":1605632} -{"case":"gcdsum","lang":"c","status":"ok","output":"7201567","expected":"7201567","rss":1458176} -{"case":"gcdsum","lang":"csharp","status":"ok","output":"7201567","expected":"7201567","rss":7143424} -{"case":"gcdsum","lang":"dart","status":"ok","output":"7201567","expected":"7201567","rss":14467072} -{"case":"gcdsum","lang":"ocaml","status":"ok","output":"7201567","expected":"7201567","rss":2326528} -{"case":"gcdsum","lang":"haskell","status":"ok","output":"7201567","expected":"7201567","rss":11616256} +{"case":"gcdsum","lang":"osprey","status":"ok","output":"7201567","expected":"7201567","rss":1556480} +{"case":"gcdsum","lang":"osprey-arc","status":"ok","output":"7201567","expected":"7201567","rss":1589248} +{"case":"gcdsum","lang":"osprey-gc","status":"ok","output":"7201567","expected":"7201567","rss":23396352} +{"case":"gcdsum","lang":"rust","status":"ok","output":"7201567","expected":"7201567","rss":1654784} +{"case":"gcdsum","lang":"c","status":"ok","output":"7201567","expected":"7201567","rss":1507328} +{"case":"gcdsum","lang":"csharp","status":"ok","output":"7201567","expected":"7201567","rss":7192576} +{"case":"gcdsum","lang":"dart","status":"ok","output":"7201567","expected":"7201567","rss":14647296} +{"case":"gcdsum","lang":"ocaml","status":"ok","output":"7201567","expected":"7201567","rss":2375680} +{"case":"gcdsum","lang":"haskell","status":"ok","output":"7201567","expected":"7201567","rss":11665408} +{"case":"gcdsum","lang":"osprey-wasm","status":"ok","output":"7201567","expected":"7201567","rss":0} {"case":"gcdsum","lang":"rust-wasm","status":"ok","output":"7201567","expected":"7201567","rss":0} -{"case":"hanoi","lang":"rust","status":"ok","output":"33554431","expected":"33554431","rss":1589248} -{"case":"hanoi","lang":"c","status":"ok","output":"33554431","expected":"33554431","rss":1458176} -{"case":"hanoi","lang":"csharp","status":"ok","output":"33554431","expected":"33554431","rss":7127040} -{"case":"hanoi","lang":"dart","status":"ok","output":"33554431","expected":"33554431","rss":14630912} -{"case":"hanoi","lang":"ocaml","status":"ok","output":"33554431","expected":"33554431","rss":2326528} -{"case":"hanoi","lang":"haskell","status":"ok","output":"33554431","expected":"33554431","rss":11632640} +{"case":"hanoi","lang":"osprey","status":"ok","output":"33554431","expected":"33554431","rss":1572864} +{"case":"hanoi","lang":"osprey-arc","status":"ok","output":"33554431","expected":"33554431","rss":1589248} +{"case":"hanoi","lang":"osprey-gc","status":"ok","output":"33554431","expected":"33554431","rss":23511040} +{"case":"hanoi","lang":"rust","status":"ok","output":"33554431","expected":"33554431","rss":1638400} +{"case":"hanoi","lang":"c","status":"ok","output":"33554431","expected":"33554431","rss":1507328} +{"case":"hanoi","lang":"csharp","status":"ok","output":"33554431","expected":"33554431","rss":7159808} +{"case":"hanoi","lang":"dart","status":"ok","output":"33554431","expected":"33554431","rss":14516224} +{"case":"hanoi","lang":"ocaml","status":"ok","output":"33554431","expected":"33554431","rss":2375680} +{"case":"hanoi","lang":"haskell","status":"ok","output":"33554431","expected":"33554431","rss":11698176} +{"case":"hanoi","lang":"osprey-wasm","status":"ok","output":"33554431","expected":"33554431","rss":0} {"case":"hanoi","lang":"rust-wasm","status":"ok","output":"33554431","expected":"33554431","rss":0} -{"case":"isqrt","lang":"rust","status":"ok","output":"666167500","expected":"666167500","rss":1605632} -{"case":"isqrt","lang":"c","status":"ok","output":"666167500","expected":"666167500","rss":1458176} +{"case":"isqrt","lang":"osprey","status":"ok","output":"666167500","expected":"666167500","rss":816939008} +{"case":"isqrt","lang":"osprey-arc","status":"ok","output":"666167500","expected":"666167500","rss":1589248} +{"case":"isqrt","lang":"osprey-gc","status":"ok","output":"666167500","expected":"666167500","rss":21659648} +{"case":"isqrt","lang":"rust","status":"ok","output":"666167500","expected":"666167500","rss":1654784} +{"case":"isqrt","lang":"c","status":"ok","output":"666167500","expected":"666167500","rss":1507328} {"case":"isqrt","lang":"csharp","status":"ok","output":"666167500","expected":"666167500","rss":7176192} -{"case":"isqrt","lang":"dart","status":"ok","output":"666167500","expected":"666167500","rss":14598144} -{"case":"isqrt","lang":"ocaml","status":"ok","output":"666167500","expected":"666167500","rss":2326528} -{"case":"isqrt","lang":"haskell","status":"ok","output":"666167500","expected":"666167500","rss":11616256} +{"case":"isqrt","lang":"dart","status":"ok","output":"666167500","expected":"666167500","rss":14565376} +{"case":"isqrt","lang":"ocaml","status":"ok","output":"666167500","expected":"666167500","rss":2375680} +{"case":"isqrt","lang":"haskell","status":"ok","output":"666167500","expected":"666167500","rss":11665408} +{"case":"isqrt","lang":"osprey-wasm","status":"ok","output":"666167500","expected":"666167500","rss":0} {"case":"isqrt","lang":"rust-wasm","status":"ok","output":"666167500","expected":"666167500","rss":0} -{"case":"josephus","lang":"rust","status":"ok","output":"1400177","expected":"1400177","rss":1605632} -{"case":"josephus","lang":"c","status":"ok","output":"1400177","expected":"1400177","rss":1458176} +{"case":"josephus","lang":"osprey","status":"ok","output":"1400177","expected":"1400177","rss":1556480} +{"case":"josephus","lang":"osprey-arc","status":"ok","output":"1400177","expected":"1400177","rss":1589248} +{"case":"josephus","lang":"osprey-gc","status":"ok","output":"1400177","expected":"1400177","rss":19546112} +{"case":"josephus","lang":"rust","status":"ok","output":"1400177","expected":"1400177","rss":1654784} +{"case":"josephus","lang":"c","status":"ok","output":"1400177","expected":"1400177","rss":1507328} {"case":"josephus","lang":"csharp","status":"ok","output":"1400177","expected":"1400177","rss":7159808} -{"case":"josephus","lang":"dart","status":"ok","output":"1400177","expected":"1400177","rss":14598144} -{"case":"josephus","lang":"ocaml","status":"ok","output":"1400177","expected":"1400177","rss":2342912} -{"case":"josephus","lang":"haskell","status":"ok","output":"1400177","expected":"1400177","rss":11632640} +{"case":"josephus","lang":"dart","status":"ok","output":"1400177","expected":"1400177","rss":14467072} +{"case":"josephus","lang":"ocaml","status":"ok","output":"1400177","expected":"1400177","rss":2375680} +{"case":"josephus","lang":"haskell","status":"ok","output":"1400177","expected":"1400177","rss":11681792} +{"case":"josephus","lang":"osprey-wasm","status":"ok","output":"1400177","expected":"1400177","rss":0} {"case":"josephus","lang":"rust-wasm","status":"ok","output":"1400177","expected":"1400177","rss":0} -{"case":"listops","lang":"rust","status":"ok","output":"15992435","expected":"15992435","rss":1687552} -{"case":"listops","lang":"c","status":"ok","output":"15992435","expected":"15992435","rss":1474560} -{"case":"listops","lang":"csharp","status":"ok","output":"15992435","expected":"15992435","rss":7389184} -{"case":"listops","lang":"dart","status":"ok","output":"15992435","expected":"15992435","rss":15007744} -{"case":"listops","lang":"ocaml","status":"ok","output":"15992435","expected":"15992435","rss":2654208} -{"case":"listops","lang":"haskell","status":"ok","output":"15992435","expected":"15992435","rss":11862016} +{"case":"listops","lang":"osprey","status":"ok","output":"15992435","expected":"15992435","rss":15138816} +{"case":"listops","lang":"osprey-arc","status":"ok","output":"15992435","expected":"15992435","rss":2195456} +{"case":"listops","lang":"osprey-gc","status":"ok","output":"15992435","expected":"15992435","rss":13484032} +{"case":"listops","lang":"rust","status":"ok","output":"15992435","expected":"15992435","rss":1736704} +{"case":"listops","lang":"c","status":"ok","output":"15992435","expected":"15992435","rss":1523712} +{"case":"listops","lang":"csharp","status":"ok","output":"15992435","expected":"15992435","rss":7438336} +{"case":"listops","lang":"dart","status":"ok","output":"15992435","expected":"15992435","rss":14991360} +{"case":"listops","lang":"ocaml","status":"ok","output":"15992435","expected":"15992435","rss":2703360} +{"case":"listops","lang":"haskell","status":"ok","output":"15992435","expected":"15992435","rss":11911168} +{"case":"listops","lang":"osprey-wasm","status":"ok","output":"15992435","expected":"15992435","rss":0} {"case":"listops","lang":"rust-wasm","status":"ok","output":"15992435","expected":"15992435","rss":0} -{"case":"mutual","lang":"rust","status":"ok","output":"64999","expected":"64999","rss":1589248} -{"case":"mutual","lang":"c","status":"ok","output":"64999","expected":"64999","rss":1441792} -{"case":"mutual","lang":"csharp","status":"ok","output":"64999","expected":"64999","rss":7143424} -{"case":"mutual","lang":"dart","status":"ok","output":"64999","expected":"64999","rss":14548992} -{"case":"mutual","lang":"ocaml","status":"ok","output":"64999","expected":"64999","rss":2326528} -{"case":"mutual","lang":"haskell","status":"ok","output":"64999","expected":"64999","rss":11632640} +{"case":"mutual","lang":"osprey","status":"ok","output":"64999","expected":"64999","rss":1540096} +{"case":"mutual","lang":"osprey-arc","status":"ok","output":"64999","expected":"64999","rss":1589248} +{"case":"mutual","lang":"osprey-gc","status":"ok","output":"64999","expected":"64999","rss":7634944} +{"case":"mutual","lang":"rust","status":"ok","output":"64999","expected":"64999","rss":1638400} +{"case":"mutual","lang":"c","status":"ok","output":"64999","expected":"64999","rss":1490944} +{"case":"mutual","lang":"csharp","status":"ok","output":"64999","expected":"64999","rss":7192576} +{"case":"mutual","lang":"dart","status":"ok","output":"64999","expected":"64999","rss":14663680} +{"case":"mutual","lang":"ocaml","status":"ok","output":"64999","expected":"64999","rss":2375680} +{"case":"mutual","lang":"haskell","status":"ok","output":"64999","expected":"64999","rss":11681792} +{"case":"mutual","lang":"osprey-wasm","status":"ok","output":"64999","expected":"64999","rss":0} {"case":"mutual","lang":"rust-wasm","status":"ok","output":"64999","expected":"64999","rss":0} -{"case":"nestedloop","lang":"rust","status":"ok","output":"255643180","expected":"255643180","rss":1589248} -{"case":"nestedloop","lang":"c","status":"ok","output":"255643180","expected":"255643180","rss":1458176} -{"case":"nestedloop","lang":"csharp","status":"ok","output":"255643180","expected":"255643180","rss":7127040} -{"case":"nestedloop","lang":"dart","status":"ok","output":"255643180","expected":"255643180","rss":14581760} -{"case":"nestedloop","lang":"ocaml","status":"ok","output":"255643180","expected":"255643180","rss":2310144} -{"case":"nestedloop","lang":"haskell","status":"ok","output":"255643180","expected":"255643180","rss":11567104} +{"case":"nestedloop","lang":"osprey","status":"ok","output":"255643180","expected":"255643180","rss":1572864} +{"case":"nestedloop","lang":"osprey-arc","status":"ok","output":"255643180","expected":"255643180","rss":1572864} +{"case":"nestedloop","lang":"osprey-gc","status":"ok","output":"255643180","expected":"255643180","rss":21151744} +{"case":"nestedloop","lang":"rust","status":"ok","output":"255643180","expected":"255643180","rss":1638400} +{"case":"nestedloop","lang":"c","status":"ok","output":"255643180","expected":"255643180","rss":1507328} +{"case":"nestedloop","lang":"csharp","status":"ok","output":"255643180","expected":"255643180","rss":7176192} +{"case":"nestedloop","lang":"dart","status":"ok","output":"255643180","expected":"255643180","rss":14598144} +{"case":"nestedloop","lang":"ocaml","status":"ok","output":"255643180","expected":"255643180","rss":2342912} +{"case":"nestedloop","lang":"haskell","status":"ok","output":"255643180","expected":"255643180","rss":11616256} +{"case":"nestedloop","lang":"osprey-wasm","status":"ok","output":"255643180","expected":"255643180","rss":0} {"case":"nestedloop","lang":"rust-wasm","status":"ok","output":"255643180","expected":"255643180","rss":0} -{"case":"pascal","lang":"rust","status":"ok","output":"20058300","expected":"20058300","rss":1589248} -{"case":"pascal","lang":"c","status":"ok","output":"20058300","expected":"20058300","rss":1458176} -{"case":"pascal","lang":"csharp","status":"ok","output":"20058300","expected":"20058300","rss":7127040} +{"case":"pascal","lang":"osprey","status":"ok","output":"20058300","expected":"20058300","rss":1589248} +{"case":"pascal","lang":"osprey-arc","status":"ok","output":"20058300","expected":"20058300","rss":1589248} +{"case":"pascal","lang":"osprey-gc","status":"ok","output":"20058300","expected":"20058300","rss":19513344} +{"case":"pascal","lang":"rust","status":"ok","output":"20058300","expected":"20058300","rss":1638400} +{"case":"pascal","lang":"c","status":"ok","output":"20058300","expected":"20058300","rss":1507328} +{"case":"pascal","lang":"csharp","status":"ok","output":"20058300","expected":"20058300","rss":7192576} {"case":"pascal","lang":"dart","status":"ok","output":"20058300","expected":"20058300","rss":14548992} -{"case":"pascal","lang":"ocaml","status":"ok","output":"20058300","expected":"20058300","rss":2326528} -{"case":"pascal","lang":"haskell","status":"ok","output":"20058300","expected":"20058300","rss":11632640} +{"case":"pascal","lang":"ocaml","status":"ok","output":"20058300","expected":"20058300","rss":2359296} +{"case":"pascal","lang":"haskell","status":"ok","output":"20058300","expected":"20058300","rss":11681792} +{"case":"pascal","lang":"osprey-wasm","status":"ok","output":"20058300","expected":"20058300","rss":0} {"case":"pascal","lang":"rust-wasm","status":"ok","output":"20058300","expected":"20058300","rss":0} -{"case":"powmod","lang":"rust","status":"ok","output":"980475159","expected":"980475159","rss":1605632} -{"case":"powmod","lang":"c","status":"ok","output":"980475159","expected":"980475159","rss":1458176} -{"case":"powmod","lang":"csharp","status":"ok","output":"980475159","expected":"980475159","rss":7143424} +{"case":"powmod","lang":"osprey","status":"ok","output":"980475159","expected":"980475159","rss":1572864} +{"case":"powmod","lang":"osprey-arc","status":"ok","output":"980475159","expected":"980475159","rss":1605632} +{"case":"powmod","lang":"osprey-gc","status":"ok","output":"980475159","expected":"980475159","rss":21659648} +{"case":"powmod","lang":"rust","status":"ok","output":"980475159","expected":"980475159","rss":1654784} +{"case":"powmod","lang":"c","status":"ok","output":"980475159","expected":"980475159","rss":1507328} +{"case":"powmod","lang":"csharp","status":"ok","output":"980475159","expected":"980475159","rss":7208960} {"case":"powmod","lang":"dart","status":"ok","output":"980475159","expected":"980475159","rss":14630912} -{"case":"powmod","lang":"ocaml","status":"ok","output":"980475159","expected":"980475159","rss":2326528} -{"case":"powmod","lang":"haskell","status":"ok","output":"980475159","expected":"980475159","rss":11632640} +{"case":"powmod","lang":"ocaml","status":"ok","output":"980475159","expected":"980475159","rss":2408448} +{"case":"powmod","lang":"haskell","status":"ok","output":"980475159","expected":"980475159","rss":11681792} +{"case":"powmod","lang":"osprey-wasm","status":"ok","output":"980475159","expected":"980475159","rss":0} {"case":"powmod","lang":"rust-wasm","status":"ok","output":"980475159","expected":"980475159","rss":0} -{"case":"primes","lang":"rust","status":"ok","output":"17984","expected":"17984","rss":1589248} -{"case":"primes","lang":"c","status":"ok","output":"17984","expected":"17984","rss":1441792} -{"case":"primes","lang":"csharp","status":"ok","output":"17984","expected":"17984","rss":7143424} -{"case":"primes","lang":"dart","status":"ok","output":"17984","expected":"17984","rss":14581760} -{"case":"primes","lang":"ocaml","status":"ok","output":"17984","expected":"17984","rss":2310144} -{"case":"primes","lang":"haskell","status":"ok","output":"17984","expected":"17984","rss":11616256} +{"case":"primes","lang":"osprey","status":"ok","output":"17984","expected":"17984","rss":1589248} +{"case":"primes","lang":"osprey-arc","status":"ok","output":"17984","expected":"17984","rss":1589248} +{"case":"primes","lang":"osprey-gc","status":"ok","output":"17984","expected":"17984","rss":20578304} +{"case":"primes","lang":"rust","status":"ok","output":"17984","expected":"17984","rss":1638400} +{"case":"primes","lang":"c","status":"ok","output":"17984","expected":"17984","rss":1507328} +{"case":"primes","lang":"csharp","status":"ok","output":"17984","expected":"17984","rss":7208960} +{"case":"primes","lang":"dart","status":"ok","output":"17984","expected":"17984","rss":14630912} +{"case":"primes","lang":"ocaml","status":"ok","output":"17984","expected":"17984","rss":2359296} +{"case":"primes","lang":"haskell","status":"ok","output":"17984","expected":"17984","rss":11681792} +{"case":"primes","lang":"osprey-wasm","status":"ok","output":"17984","expected":"17984","rss":0} {"case":"primes","lang":"rust-wasm","status":"ok","output":"17984","expected":"17984","rss":0} -{"case":"tak","lang":"rust","status":"ok","output":"9","expected":"9","rss":1589248} -{"case":"tak","lang":"c","status":"ok","output":"9","expected":"9","rss":1441792} -{"case":"tak","lang":"csharp","status":"ok","output":"9","expected":"9","rss":7143424} -{"case":"tak","lang":"dart","status":"ok","output":"9","expected":"9","rss":14532608} -{"case":"tak","lang":"ocaml","status":"ok","output":"9","expected":"9","rss":2326528} -{"case":"tak","lang":"haskell","status":"ok","output":"9","expected":"9","rss":11632640} +{"case":"tak","lang":"osprey","status":"ok","output":"9","expected":"9","rss":1572864} +{"case":"tak","lang":"osprey-arc","status":"ok","output":"9","expected":"9","rss":1605632} +{"case":"tak","lang":"osprey-gc","status":"ok","output":"9","expected":"9","rss":21528576} +{"case":"tak","lang":"rust","status":"ok","output":"9","expected":"9","rss":1638400} +{"case":"tak","lang":"c","status":"ok","output":"9","expected":"9","rss":1490944} +{"case":"tak","lang":"csharp","status":"ok","output":"9","expected":"9","rss":7208960} +{"case":"tak","lang":"dart","status":"ok","output":"9","expected":"9","rss":14598144} +{"case":"tak","lang":"ocaml","status":"ok","output":"9","expected":"9","rss":2392064} +{"case":"tak","lang":"haskell","status":"ok","output":"9","expected":"9","rss":11698176} +{"case":"tak","lang":"osprey-wasm","status":"ok","output":"9","expected":"9","rss":0} {"case":"tak","lang":"rust-wasm","status":"ok","output":"9","expected":"9","rss":0} -{"case":"textstats","lang":"rust","status":"ok","output":"1574956","expected":"1574956","rss":1638400} -{"case":"textstats","lang":"c","status":"ok","output":"1574956","expected":"1574956","rss":1458176} -{"case":"textstats","lang":"csharp","status":"ok","output":"1574956","expected":"1574956","rss":7110656} -{"case":"textstats","lang":"dart","status":"ok","output":"1574956","expected":"1574956","rss":14663680} -{"case":"textstats","lang":"ocaml","status":"ok","output":"1574956","expected":"1574956","rss":2392064} -{"case":"textstats","lang":"haskell","status":"ok","output":"1574956","expected":"1574956","rss":11911168} +{"case":"textstats","lang":"osprey","status":"ok","output":"1574956","expected":"1574956","rss":1589248} +{"case":"textstats","lang":"osprey-arc","status":"ok","output":"1574956","expected":"1574956","rss":1638400} +{"case":"textstats","lang":"osprey-gc","status":"ok","output":"1574956","expected":"1574956","rss":19529728} +{"case":"textstats","lang":"rust","status":"ok","output":"1574956","expected":"1574956","rss":1687552} +{"case":"textstats","lang":"c","status":"ok","output":"1574956","expected":"1574956","rss":1507328} +{"case":"textstats","lang":"csharp","status":"ok","output":"1574956","expected":"1574956","rss":7159808} +{"case":"textstats","lang":"dart","status":"ok","output":"1574956","expected":"1574956","rss":14680064} +{"case":"textstats","lang":"ocaml","status":"ok","output":"1574956","expected":"1574956","rss":2424832} +{"case":"textstats","lang":"haskell","status":"ok","output":"1574956","expected":"1574956","rss":11960320} +{"case":"textstats","lang":"osprey-wasm","status":"ok","output":"1574956","expected":"1574956","rss":0} {"case":"textstats","lang":"rust-wasm","status":"ok","output":"1574956","expected":"1574956","rss":0} -{"case":"wordfreq","lang":"rust","status":"ok","output":"900036","expected":"900036","rss":1654784} -{"case":"wordfreq","lang":"c","status":"ok","output":"900036","expected":"900036","rss":1441792} -{"case":"wordfreq","lang":"csharp","status":"ok","output":"900036","expected":"900036","rss":7094272} +{"case":"wordfreq","lang":"osprey","status":"ok","output":"900036","expected":"900036","rss":61947904} +{"case":"wordfreq","lang":"osprey-arc","status":"ok","output":"900036","expected":"900036","rss":1720320} +{"case":"wordfreq","lang":"osprey-gc","status":"ok","output":"900036","expected":"900036","rss":18890752} +{"case":"wordfreq","lang":"rust","status":"ok","output":"900036","expected":"900036","rss":1703936} +{"case":"wordfreq","lang":"c","status":"ok","output":"900036","expected":"900036","rss":1490944} +{"case":"wordfreq","lang":"csharp","status":"ok","output":"900036","expected":"900036","rss":7143424} {"case":"wordfreq","lang":"dart","status":"ok","output":"900036","expected":"900036","rss":14663680} -{"case":"wordfreq","lang":"ocaml","status":"ok","output":"900036","expected":"900036","rss":2408448} -{"case":"wordfreq","lang":"haskell","status":"ok","output":"900036","expected":"900036","rss":11862016} +{"case":"wordfreq","lang":"ocaml","status":"ok","output":"900036","expected":"900036","rss":2457600} +{"case":"wordfreq","lang":"haskell","status":"ok","output":"900036","expected":"900036","rss":11911168} +{"case":"wordfreq","lang":"osprey-wasm","status":"ok","output":"900036","expected":"900036","rss":0} {"case":"wordfreq","lang":"rust-wasm","status":"ok","output":"900036","expected":"900036","rss":0} -{"case":"ackermann","lang":"osprey","status":"ok","output":"8189","expected":"8189","rss":2155855872} -{"case":"ackermann","lang":"osprey-arc","status":"ok","output":"8189","expected":"8189","rss":2031616} -{"case":"ackermann","lang":"osprey-gc","status":"ok","output":"8189","expected":"8189","rss":19972096} -{"case":"binarytrees","lang":"osprey","status":"ok","output":"19659600","expected":"19659600","rss":2527870976} -{"case":"binarytrees","lang":"osprey-arc","status":"ok","output":"19659600","expected":"19659600","rss":2981888} -{"case":"binarytrees","lang":"osprey-gc","status":"ok","output":"19659600","expected":"19659600","rss":19103744} -{"case":"coins","lang":"osprey","status":"ok","output":"116727","expected":"116727","rss":1437876224} -{"case":"coins","lang":"osprey-arc","status":"ok","output":"116727","expected":"116727","rss":1556480} -{"case":"coins","lang":"osprey-gc","status":"ok","output":"116727","expected":"116727","rss":20037632} -{"case":"collatz","lang":"osprey","status":"ok","output":"10753840","expected":"10753840","rss":1155743744} -{"case":"collatz","lang":"osprey-arc","status":"ok","output":"10753840","expected":"10753840","rss":1540096} -{"case":"collatz","lang":"osprey-gc","status":"ok","output":"10753840","expected":"10753840","rss":21594112} -{"case":"coprime","lang":"osprey","status":"ok","output":"2433175","expected":"2433175","rss":1040334848} -{"case":"coprime","lang":"osprey-arc","status":"ok","output":"2433175","expected":"2433175","rss":1540096} -{"case":"coprime","lang":"osprey-gc","status":"ok","output":"2433175","expected":"2433175","rss":19513344} -{"case":"digitsum","lang":"osprey","status":"ok","output":"55000002","expected":"55000002","rss":1115258880} -{"case":"digitsum","lang":"osprey-arc","status":"ok","output":"55000002","expected":"55000002","rss":1523712} -{"case":"digitsum","lang":"osprey-gc","status":"ok","output":"55000002","expected":"55000002","rss":19759104} -{"case":"exprtree","lang":"osprey","status":"ok","output":"900720437","expected":"900720437","rss":114753536} -{"case":"exprtree","lang":"osprey-arc","status":"ok","output":"900720437","expected":"900720437","rss":3522560} -{"case":"exprtree","lang":"osprey-gc","status":"ok","output":"900720437","expected":"900720437","rss":19431424} -{"case":"factorial","lang":"osprey","status":"ok","output":"682498929","expected":"682498929","rss":644055040} -{"case":"factorial","lang":"osprey-arc","status":"ok","output":"682498929","expected":"682498929","rss":1523712} -{"case":"factorial","lang":"osprey-gc","status":"ok","output":"682498929","expected":"682498929","rss":20578304} -{"case":"fib","lang":"osprey","status":"ok","output":"9227465","expected":"9227465","rss":1440481280} -{"case":"fib","lang":"osprey-arc","status":"ok","output":"9227465","expected":"9227465","rss":1523712} -{"case":"fib","lang":"osprey-gc","status":"ok","output":"9227465","expected":"9227465","rss":19513344} -{"case":"gcdsum","lang":"osprey","status":"ok","output":"7201567","expected":"7201567","rss":912244736} -{"case":"gcdsum","lang":"osprey-arc","status":"ok","output":"7201567","expected":"7201567","rss":1523712} -{"case":"gcdsum","lang":"osprey-gc","status":"ok","output":"7201567","expected":"7201567","rss":19742720} -{"case":"hanoi","lang":"osprey","status":"ok","output":"33554431","expected":"33554431","rss":3235397632} -{"case":"hanoi","lang":"osprey-arc","status":"ok","output":"33554431","expected":"33554431","rss":1540096} -{"case":"hanoi","lang":"osprey-gc","status":"ok","output":"33554431","expected":"33554431","rss":21594112} -{"case":"isqrt","lang":"osprey","status":"ok","output":"666167500","expected":"666167500","rss":1256669184} -{"case":"isqrt","lang":"osprey-arc","status":"ok","output":"666167500","expected":"666167500","rss":1540096} -{"case":"isqrt","lang":"osprey-gc","status":"ok","output":"666167500","expected":"666167500","rss":20021248} -{"case":"josephus","lang":"osprey","status":"ok","output":"1400177","expected":"1400177","rss":644087808} -{"case":"josephus","lang":"osprey-arc","status":"ok","output":"1400177","expected":"1400177","rss":1556480} -{"case":"josephus","lang":"osprey-gc","status":"ok","output":"1400177","expected":"1400177","rss":19496960} -{"case":"listops","lang":"osprey","status":"ok","output":"15992435","expected":"15992435","rss":23314432} -{"case":"listops","lang":"osprey-arc","status":"ok","output":"15992435","expected":"15992435","rss":2146304} -{"case":"listops","lang":"osprey-gc","status":"ok","output":"15992435","expected":"15992435","rss":14680064} -{"case":"mutual","lang":"osprey","status":"ok","output":"64999","expected":"64999","rss":2093891584} -{"case":"mutual","lang":"osprey-arc","status":"ok","output":"64999","expected":"64999","rss":1540096} -{"case":"mutual","lang":"osprey-gc","status":"ok","output":"64999","expected":"64999","rss":19464192} -{"case":"nestedloop","lang":"osprey","status":"ok","output":"255643180","expected":"255643180","rss":2513387520} -{"case":"nestedloop","lang":"osprey-arc","status":"ok","output":"255643180","expected":"255643180","rss":1523712} -{"case":"nestedloop","lang":"osprey-gc","status":"ok","output":"255643180","expected":"255643180","rss":19496960} -{"case":"pascal","lang":"osprey","status":"ok","output":"20058300","expected":"20058300","rss":2579070976} -{"case":"pascal","lang":"osprey-arc","status":"ok","output":"20058300","expected":"20058300","rss":1540096} -{"case":"pascal","lang":"osprey-gc","status":"ok","output":"20058300","expected":"20058300","rss":19480576} -{"case":"powmod","lang":"osprey","status":"ok","output":"980475159","expected":"980475159","rss":1993375744} -{"case":"powmod","lang":"osprey-arc","status":"ok","output":"980475159","expected":"980475159","rss":1556480} -{"case":"powmod","lang":"osprey-gc","status":"ok","output":"980475159","expected":"980475159","rss":19480576} -{"case":"primes","lang":"osprey","status":"ok","output":"17984","expected":"17984","rss":687669248} -{"case":"primes","lang":"osprey-arc","status":"ok","output":"17984","expected":"17984","rss":1556480} -{"case":"primes","lang":"osprey-gc","status":"ok","output":"17984","expected":"17984","rss":19447808} -{"case":"tak","lang":"osprey","status":"ok","output":"9","expected":"9","rss":1218543616} -{"case":"tak","lang":"osprey-arc","status":"ok","output":"9","expected":"9","rss":1523712} -{"case":"tak","lang":"osprey-gc","status":"ok","output":"9","expected":"9","rss":19759104} -{"case":"textstats","lang":"osprey","status":"ok","output":"1574956","expected":"1574956","rss":59424768} -{"case":"textstats","lang":"osprey-arc","status":"ok","output":"1574956","expected":"1574956","rss":1605632} -{"case":"textstats","lang":"osprey-gc","status":"ok","output":"1574956","expected":"1574956","rss":15548416} -{"case":"wordfreq","lang":"osprey","status":"ok","output":"900036","expected":"900036","rss":106905600} -{"case":"wordfreq","lang":"osprey-arc","status":"ok","output":"900036","expected":"900036","rss":1654784} -{"case":"wordfreq","lang":"osprey-gc","status":"ok","output":"900036","expected":"900036","rss":18972672} diff --git a/benchmarks/results/results.html b/benchmarks/results/results.html index 1f94e4bf..1cb14fa9 100644 --- a/benchmarks/results/results.html +++ b/benchmarks/results/results.html @@ -1368,13 +1368,13 @@

Osprey cross-language benchmarks

-

Osprey, Osprey (ARC), Osprey (GC), Rust, C, C# (AOT), Dart (AOT), OCaml, Haskell, Rust (wasm) — same naive algorithm and parameters in every language, native +

Osprey, Osprey (ARC), Osprey (GC), Rust, C, C# (AOT), Dart (AOT), OCaml, Haskell, Osprey (wasm), Rust (wasm) — same naive algorithm and parameters in every language, native release builds, output checked against an integer oracle. CPU = hyperfine mean ± stddev; memory = peak resident set size. Generated mechanically by benchmarks/report.py; re-run with make bench.

-
0CPU wins (fastest of all)
13.64×CPU vs Rust
15.43×CPU vs C
11.05×CPU vs C# (AOT)
5.49×CPU vs Dart (AOT)
10.60×CPU vs OCaml
7.35×CPU vs Haskell
6.91×CPU vs Rust (wasm)

Osprey is the fastest of all five languages on . Lower is better; ★ marks an Osprey win.

+
0CPU wins (fastest of all)
11.59×CPU vs Rust
13.14×CPU vs C
9.19×CPU vs C# (AOT)
4.69×CPU vs Dart (AOT)
8.91×CPU vs OCaml
6.25×CPU vs Haskell
5.65×CPU vs Rust (wasm)

Osprey is the fastest of all five languages on . Lower is better; ★ marks an Osprey win.

CPU time

-
BenchmarkOspreyOsprey (ARC)Osprey (GC)RustCC# (AOT)Dart (AOT)OCamlHaskellRust (wasm)
ackermann914.6 ms864.2 ms4.949 s128.9 ms130.7 ms130.4 ms184.7 ms110.8 ms64.2 ms144.9 ms
binarytrees1.076 s1.301 s4.806 s726.8 ms356.2 ms127.3 ms124.7 ms52.3 ms16.8 ms810.4 ms
coins611.4 ms573.6 ms3.444 s82.6 ms81.0 ms101.6 ms122.3 ms100.5 ms53.9 ms110.8 ms
collatz480.2 ms463.9 ms2.669 s13.0 ms10.4 ms58.9 ms67.5 ms60.1 ms39.3 ms24.6 ms
coprime390.1 ms373.1 ms2.289 s65.7 ms63.7 ms78.2 ms113.2 ms90.7 ms105.7 ms77.3 ms
digitsum408.3 ms397.7 ms2.458 s5.7 ms5.6 ms16.4 ms29.2 ms18.7 ms32.3 ms19.1 ms
exprtree44.4 ms47.9 ms281.2 ms10.8 ms6.3 ms6.5 ms14.3 ms5.3 ms18.1 ms20.6 ms
factorial237.2 ms224.5 ms1.421 s35.5 ms35.4 ms37.2 ms51.7 ms48.7 ms57.4 ms48.6 ms
fib555.6 ms536.0 ms3.171 s17.6 ms18.4 ms36.6 ms52.2 ms24.2 ms48.0 ms37.3 ms
gcdsum331.1 ms323.4 ms1.996 s79.5 ms79.5 ms86.2 ms110.5 ms101.9 ms106.5 ms92.1 ms
hanoi1.254 s1.244 s7.289 s38.9 ms41.0 ms44.9 ms120.1 ms62.8 ms58.2 ms53.1 ms
isqrt445.2 ms444.3 ms2.717 s11.2 ms10.8 ms17.5 ms34.0 ms21.3 ms45.3 ms23.4 ms
josephus232.3 ms225.6 ms1.413 s33.5 ms33.4 ms35.3 ms43.2 ms41.6 ms45.7 ms45.3 ms
listops6.9 ms7.4 ms24.4 ms1.6 ms1.4 ms3.2 ms11.1 ms2.2 ms16.6 ms12.8 ms
mutual730.0 ms685.5 ms4.563 s13.2 ms12.9 ms21.6 ms329.6 ms28.3 ms40.0 ms30.0 ms
nestedloop866.9 ms862.0 ms5.372 s46.2 ms45.9 ms47.8 ms61.4 ms58.2 ms64.4 ms62.5 ms
pascal963.0 ms962.7 ms5.549 s27.8 ms28.2 ms34.4 ms70.6 ms50.4 ms64.2 ms48.1 ms
powmod687.1 ms679.4 ms4.332 s23.9 ms23.8 ms34.5 ms51.3 ms61.4 ms60.3 ms34.6 ms
primes238.5 ms229.8 ms1.473 s6.9 ms6.6 ms8.8 ms44.9 ms9.1 ms17.9 ms17.3 ms
tak471.4 ms468.8 ms2.567 s33.2 ms33.0 ms35.7 ms82.6 ms45.1 ms68.5 ms99.3 ms
textstats23.8 ms24.8 ms123.2 ms2.0 ms2.1 ms3.7 ms11.8 ms4.0 ms17.8 ms12.8 ms
wordfreq40.9 ms47.8 ms187.4 ms4.5 ms1.5 ms3.3 ms11.5 ms2.6 ms17.8 ms15.7 ms
+
BenchmarkOspreyOsprey (ARC)Osprey (GC)RustCC# (AOT)Dart (AOT)OCamlHaskellOsprey (wasm)Rust (wasm)
ackermann1.382 s860.8 ms5.514 s129.3 ms130.6 ms132.4 ms185.3 ms111.3 ms65.3 mswrong✗145.5 ms
binarytrees1.224 s1.156 s5.346 s743.8 ms362.9 ms128.4 ms128.6 ms52.3 ms17.0 ms1.165 s818.6 ms
coins660.2 ms416.7 ms2.582 s84.5 ms79.8 ms104.4 ms126.0 ms103.3 ms52.3 ms466.5 ms114.0 ms
collatz516.9 ms343.7 ms2.162 s13.4 ms10.8 ms59.3 ms72.7 ms64.6 ms40.2 ms380.3 ms25.4 ms
coprime189.7 ms148.4 ms703.3 ms66.4 ms65.0 ms80.5 ms111.6 ms119.4 ms220.3 ms296.5 ms163.3 ms
digitsum686.9 ms397.9 ms4.629 s6.1 ms6.1 ms21.2 ms32.8 ms19.5 ms29.4 ms280.0 ms18.8 ms
exprtree46.4 ms28.1 ms148.9 ms11.1 ms6.1 ms7.7 ms15.8 ms5.1 ms16.3 ms33.7 ms20.4 ms
factorial35.8 ms35.5 ms35.4 ms35.6 ms35.3 ms37.4 ms51.2 ms48.7 ms53.5 ms44.7 ms48.6 ms
fib1.097 s600.5 ms4.502 s22.7 ms23.4 ms43.3 ms59.8 ms29.5 ms56.5 ms684.9 ms49.4 ms
gcdsum133.9 ms120.1 ms241.2 ms86.1 ms86.5 ms92.8 ms122.0 ms107.7 ms115.0 ms126.5 ms104.3 ms
hanoi1.766 s979.3 ms5.488 s37.5 ms38.5 ms38.7 ms103.9 ms62.9 ms54.4 ms766.1 ms52.3 ms
isqrt563.8 ms414.3 ms3.009 s10.9 ms10.6 ms17.1 ms32.5 ms20.6 ms41.0 ms412.9 ms22.9 ms
josephus380.1 ms222.2 ms1.513 s33.8 ms33.4 ms35.9 ms42.0 ms42.0 ms44.5 ms243.7 ms44.4 ms
listops7.2 ms6.1 ms17.4 ms1.5 ms1.3 ms3.3 ms10.8 ms2.2 ms16.6 ms13.4 ms12.5 ms
mutual19.3 ms18.3 ms19.7 ms13.1 ms12.9 ms21.5 ms335.0 ms29.1 ms40.7 ms40.4 ms30.0 ms
nestedloop870.6 ms503.7 ms3.463 s46.4 ms46.0 ms48.4 ms60.6 ms58.5 ms65.2 ms381.6 ms62.9 ms
pascal1.602 s936.7 ms6.487 s27.9 ms28.2 ms34.1 ms65.2 ms45.1 ms65.0 ms970.5 ms46.9 ms
powmod883.9 ms498.5 ms4.019 s27.4 ms27.5 ms40.1 ms58.8 ms71.1 ms65.4 ms407.8 ms39.5 ms
primes316.4 ms171.6 ms1.257 s7.1 ms7.1 ms10.7 ms52.6 ms10.0 ms18.7 ms144.4 ms21.0 ms
tak598.0 ms363.7 ms2.673 s37.5 ms37.3 ms40.5 ms93.3 ms51.2 ms75.0 ms480.5 ms92.0 ms
textstats23.3 ms16.0 ms75.1 ms2.0 ms2.2 ms3.8 ms11.4 ms4.0 ms16.7 ms25.2 ms14.9 ms
wordfreq37.5 ms40.3 ms141.7 ms4.5 ms1.5 ms3.3 ms10.6 ms2.5 ms16.4 ms45.7 ms15.7 ms

Peak memory

-
BenchmarkOspreyOsprey (ARC)Osprey (GC)RustCC# (AOT)Dart (AOT)OCamlHaskellRust (wasm)
ackermann2056.0 MiB1.9 MiB19.0 MiB1.8 MiB1.6 MiB7.0 MiB14.0 MiB2.6 MiB15.1 MiB
binarytrees2410.8 MiB2.8 MiB18.2 MiB2.1 MiB1.7 MiB16.1 MiB22.5 MiB5.1 MiB11.0 MiB
coins1371.3 MiB1.5 MiB19.1 MiB1.5 MiB1.4 MiB6.8 MiB13.9 MiB2.2 MiB11.1 MiB
collatz1102.2 MiB1.5 MiB20.6 MiB1.5 MiB1.4 MiB6.8 MiB13.9 MiB2.2 MiB11.1 MiB
coprime992.1 MiB1.5 MiB18.6 MiB1.5 MiB1.4 MiB6.8 MiB13.9 MiB2.2 MiB11.1 MiB
digitsum1063.6 MiB1.5 MiB18.8 MiB1.5 MiB1.4 MiB6.8 MiB13.9 MiB2.2 MiB11.1 MiB
exprtree109.4 MiB3.4 MiB18.5 MiB2.6 MiB11.4 MiB15.2 MiB22.5 MiB6.0 MiB11.3 MiB
factorial614.2 MiB1.5 MiB19.6 MiB1.5 MiB1.4 MiB6.8 MiB13.8 MiB2.2 MiB11.1 MiB
fib1373.8 MiB1.5 MiB18.6 MiB1.5 MiB1.4 MiB6.8 MiB13.9 MiB2.2 MiB11.1 MiB
gcdsum870.0 MiB1.5 MiB18.8 MiB1.5 MiB1.4 MiB6.8 MiB13.8 MiB2.2 MiB11.1 MiB
hanoi3085.5 MiB1.5 MiB20.6 MiB1.5 MiB1.4 MiB6.8 MiB14.0 MiB2.2 MiB11.1 MiB
isqrt1198.5 MiB1.5 MiB19.1 MiB1.5 MiB1.4 MiB6.8 MiB13.9 MiB2.2 MiB11.1 MiB
josephus614.2 MiB1.5 MiB18.6 MiB1.5 MiB1.4 MiB6.8 MiB13.9 MiB2.2 MiB11.1 MiB
listops22.2 MiB2.0 MiB14.0 MiB1.6 MiB1.4 MiB7.0 MiB14.3 MiB2.5 MiB11.3 MiB
mutual1996.9 MiB1.5 MiB18.6 MiB1.5 MiB1.4 MiB6.8 MiB13.9 MiB2.2 MiB11.1 MiB
nestedloop2397.0 MiB1.5 MiB18.6 MiB1.5 MiB1.4 MiB6.8 MiB13.9 MiB2.2 MiB11.0 MiB
pascal2459.6 MiB1.5 MiB18.6 MiB1.5 MiB1.4 MiB6.8 MiB13.9 MiB2.2 MiB11.1 MiB
powmod1901.0 MiB1.5 MiB18.6 MiB1.5 MiB1.4 MiB6.8 MiB14.0 MiB2.2 MiB11.1 MiB
primes655.8 MiB1.5 MiB18.5 MiB1.5 MiB1.4 MiB6.8 MiB13.9 MiB2.2 MiB11.1 MiB
tak1162.1 MiB1.5 MiB18.8 MiB1.5 MiB1.4 MiB6.8 MiB13.9 MiB2.2 MiB11.1 MiB
textstats56.7 MiB1.5 MiB14.8 MiB1.6 MiB1.4 MiB6.8 MiB14.0 MiB2.3 MiB11.4 MiB
wordfreq102.0 MiB1.6 MiB18.1 MiB1.6 MiB1.4 MiB6.8 MiB14.0 MiB2.3 MiB11.3 MiB
+
BenchmarkOspreyOsprey (ARC)Osprey (GC)RustCC# (AOT)Dart (AOT)OCamlHaskellOsprey (wasm)Rust (wasm)
ackermann2.0 MiB2.0 MiB21.0 MiB1.8 MiB1.7 MiB7.1 MiB14.0 MiB2.7 MiB15.1 MiBwrong✗
binarytrees1808.5 MiB2.9 MiB20.3 MiB2.2 MiB1.8 MiB16.1 MiB22.5 MiB5.2 MiB11.1 MiB
coins1.5 MiB1.5 MiB20.5 MiB1.6 MiB1.5 MiB6.8 MiB13.9 MiB2.3 MiB11.1 MiB
collatz221.8 MiB1.5 MiB18.5 MiB1.6 MiB1.4 MiB6.9 MiB14.0 MiB2.3 MiB11.1 MiB
coprime1.5 MiB1.5 MiB18.7 MiB1.6 MiB1.4 MiB6.8 MiB14.0 MiB2.3 MiB11.1 MiB
digitsum335.1 MiB1.5 MiB22.0 MiB1.6 MiB1.4 MiB6.9 MiB14.0 MiB2.3 MiB11.1 MiB
exprtree9.1 MiB3.4 MiB18.5 MiB2.7 MiB11.5 MiB15.2 MiB22.5 MiB6.1 MiB11.4 MiB
factorial1.5 MiB1.5 MiB1.5 MiB1.6 MiB1.4 MiB6.8 MiB13.9 MiB2.3 MiB11.1 MiB
fib1.5 MiB1.5 MiB22.4 MiB1.6 MiB1.4 MiB6.8 MiB13.9 MiB2.2 MiB11.2 MiB
gcdsum1.5 MiB1.5 MiB22.3 MiB1.6 MiB1.4 MiB6.9 MiB14.0 MiB2.3 MiB11.1 MiB
hanoi1.5 MiB1.5 MiB22.4 MiB1.6 MiB1.4 MiB6.8 MiB13.8 MiB2.3 MiB11.2 MiB
isqrt779.1 MiB1.5 MiB20.7 MiB1.6 MiB1.4 MiB6.8 MiB13.9 MiB2.3 MiB11.1 MiB
josephus1.5 MiB1.5 MiB18.6 MiB1.6 MiB1.4 MiB6.8 MiB13.8 MiB2.3 MiB11.1 MiB
listops14.4 MiB2.1 MiB12.9 MiB1.7 MiB1.5 MiB7.1 MiB14.3 MiB2.6 MiB11.4 MiB
mutual1.5 MiB1.5 MiB7.3 MiB1.6 MiB1.4 MiB6.9 MiB14.0 MiB2.3 MiB11.1 MiB
nestedloop1.5 MiB1.5 MiB20.2 MiB1.6 MiB1.4 MiB6.8 MiB13.9 MiB2.2 MiB11.1 MiB
pascal1.5 MiB1.5 MiB18.6 MiB1.6 MiB1.4 MiB6.9 MiB13.9 MiB2.2 MiB11.1 MiB
powmod1.5 MiB1.5 MiB20.7 MiB1.6 MiB1.4 MiB6.9 MiB14.0 MiB2.3 MiB11.1 MiB
primes1.5 MiB1.5 MiB19.6 MiB1.6 MiB1.4 MiB6.9 MiB14.0 MiB2.2 MiB11.1 MiB
tak1.5 MiB1.5 MiB20.5 MiB1.6 MiB1.4 MiB6.9 MiB13.9 MiB2.3 MiB11.2 MiB
textstats1.5 MiB1.6 MiB18.6 MiB1.6 MiB1.4 MiB6.8 MiB14.0 MiB2.3 MiB11.4 MiB
wordfreq59.1 MiB1.6 MiB18.0 MiB1.6 MiB1.4 MiB6.8 MiB14.0 MiB2.3 MiB11.4 MiB
diff --git a/benchmarks/results/results.json b/benchmarks/results/results.json index 2554eb7a..50b1d2d5 100644 --- a/benchmarks/results/results.json +++ b/benchmarks/results/results.json @@ -9,1811 +9,1984 @@ "dart", "ocaml", "haskell", + "osprey-wasm", "rust-wasm" ], "cases": { "ackermann": { + "osprey": { + "status": "ok", + "rss": 2064384, + "mean": 1.3817138834000002, + "stddev": 0.03267507729624188, + "min": 1.347664375, + "max": 1.420763 + }, + "osprey-arc": { + "status": "ok", + "rss": 2080768, + "mean": 0.8607754833000001, + "stddev": 0.009162615471803767, + "min": 0.842882208, + "max": 0.873344667 + }, + "osprey-gc": { + "status": "ok", + "rss": 22036480, + "mean": 5.5142276791, + "stddev": 0.08718276928847354, + "min": 5.407415042, + "max": 5.694212541 + }, "rust": { "status": "ok", - "rss": 1835008, - "mean": 0.1288787590869565, - "stddev": 0.0013338989395995187, - "min": 0.12715520900000002, - "max": 0.13257991700000002 + "rss": 1884160, + "mean": 0.12933040582608693, + "stddev": 0.0022675287975777573, + "min": 0.12730708300000002, + "max": 0.13795300000000002 }, "c": { "status": "ok", - "rss": 1687552, - "mean": 0.13067937869565222, - "stddev": 0.0038779279664136325, - "min": 0.126556542, - "max": 0.14347620800000002 + "rss": 1736704, + "mean": 0.13055866663636365, + "stddev": 0.0017622513262216478, + "min": 0.12822729200000002, + "max": 0.13470579200000002 }, "csharp": { "status": "ok", - "rss": 7340032, - "mean": 0.13035859608695652, - "stddev": 0.0012142663088239353, - "min": 0.12829425, - "max": 0.13271925 + "rss": 7421952, + "mean": 0.13236130877272728, + "stddev": 0.003628949616280512, + "min": 0.129366417, + "max": 0.14349683300000002 }, "dart": { "status": "ok", - "rss": 14696448, - "mean": 0.18469834637500002, - "stddev": 0.003538192914785473, - "min": 0.18134566700000002, - "max": 0.19445737500000002 + "rss": 14729216, + "mean": 0.18532129687499999, + "stddev": 0.0022041433460335247, + "min": 0.18264887500000002, + "max": 0.19045687500000003 }, "ocaml": { "status": "ok", - "rss": 2752512, - "mean": 0.11080199074074072, - "stddev": 0.0006894857979994726, - "min": 0.10944683300000001, - "max": 0.11221866700000001 + "rss": 2801664, + "mean": 0.11131183184615384, + "stddev": 0.0005185538288264928, + "min": 0.11003425, + "max": 0.11245666700000001 }, "haskell": { "status": "ok", - "rss": 15826944, - "mean": 0.06424615833333337, - "stddev": 0.0021294431157583946, - "min": 0.060423125, - "max": 0.07006991700000001 + "rss": 15876096, + "mean": 0.06527007031111111, + "stddev": 0.0023523008769594056, + "min": 0.060644250000000004, + "max": 0.07460825 + }, + "osprey-wasm": { + "status": "wrong_output", + "rss": 0 }, "rust-wasm": { "status": "ok", "rss": 0, - "mean": 0.14488908134999998, - "stddev": 0.0016793974273024634, - "min": 0.143189292, - "max": 0.150372042 - }, + "mean": 0.1455010478, + "stddev": 0.0009647097861249382, + "min": 0.144610541, + "max": 0.14924300000000001 + } + }, + "binarytrees": { "osprey": { "status": "ok", - "rss": 2155855872, - "mean": 0.9145769248999999, - "stddev": 0.007557973743778028, - "min": 0.908628791, - "max": 0.9323148330000001 + "rss": 1896349696, + "mean": 1.2240733709999998, + "stddev": 0.026799950325589565, + "min": 1.189240042, + "max": 1.277423667 }, "osprey-arc": { "status": "ok", - "rss": 2031616, - "mean": 0.8642003957, - "stddev": 0.0110863846883628, - "min": 0.8444029160000001, - "max": 0.884081709 + "rss": 3031040, + "mean": 1.1563370583, + "stddev": 0.025945464344690177, + "min": 1.126711875, + "max": 1.202355875 }, "osprey-gc": { "status": "ok", - "rss": 19972096, - "mean": 4.949318591800001, - "stddev": 0.35134580035604096, - "min": 4.640549, - "max": 5.758133917 - } - }, - "binarytrees": { + "rss": 21282816, + "mean": 5.346139153999999, + "stddev": 0.08656685448587208, + "min": 5.24070175, + "max": 5.4528701250000005 + }, "rust": { "status": "ok", - "rss": 2211840, - "mean": 0.7267523541, - "stddev": 0.016345185876649994, - "min": 0.7122952920000001, - "max": 0.770251667 + "rss": 2293760, + "mean": 0.7437713709, + "stddev": 0.019726789243382985, + "min": 0.724044625, + "max": 0.791529875 }, "c": { "status": "ok", - "rss": 1753088, - "mean": 0.3562366376, - "stddev": 0.003333752233715585, - "min": 0.350601, - "max": 0.361588 + "rss": 1835008, + "mean": 0.36291161680000006, + "stddev": 0.00309930902336544, + "min": 0.359546291, + "max": 0.36817383400000003 }, "csharp": { "status": "ok", - "rss": 16859136, - "mean": 0.1273038332173913, - "stddev": 0.0017269926397838326, - "min": 0.12476716700000001, - "max": 0.133344042 + "rss": 16891904, + "mean": 0.12843639139130433, + "stddev": 0.001132393498565589, + "min": 0.12670045900000002, + "max": 0.13042029200000002 }, "dart": { "status": "ok", - "rss": 23543808, - "mean": 0.12471422733333333, - "stddev": 0.004305733195329181, - "min": 0.12239704100000001, - "max": 0.14446545900000002 + "rss": 23560192, + "mean": 0.12861298668181817, + "stddev": 0.0015572911935333768, + "min": 0.12589308300000002, + "max": 0.134085584 }, "ocaml": { "status": "ok", - "rss": 5373952, - "mean": 0.05231316066071428, - "stddev": 0.0029111102633143275, - "min": 0.050791375, - "max": 0.07293337500000001 + "rss": 5423104, + "mean": 0.05234788308771932, + "stddev": 0.000661989937718232, + "min": 0.050869375, + "max": 0.054223209 }, "haskell": { "status": "ok", - "rss": 11550720, - "mean": 0.01675753849112425, - "stddev": 0.0009183002504076754, - "min": 0.014412958000000002, - "max": 0.018361458 + "rss": 11599872, + "mean": 0.01701369682758621, + "stddev": 0.0016864107323298124, + "min": 0.014675416, + "max": 0.033340958000000004 }, - "rust-wasm": { + "osprey-wasm": { "status": "ok", "rss": 0, - "mean": 0.8103571206, - "stddev": 0.00714477349414571, - "min": 0.79722925, - "max": 0.818866541 + "mean": 1.1645360666, + "stddev": 0.02813891871319769, + "min": 1.136059708, + "max": 1.232573917 }, + "rust-wasm": { + "status": "ok", + "rss": 0, + "mean": 0.8186353332000001, + "stddev": 0.008923778844013075, + "min": 0.799317167, + "max": 0.829746792 + } + }, + "coins": { "osprey": { "status": "ok", - "rss": 2527870976, - "mean": 1.0757269539, - "stddev": 0.011810050128214232, - "min": 1.060976208, - "max": 1.092785792 + "rss": 1572864, + "mean": 0.6602168709, + "stddev": 0.009640925576167407, + "min": 0.6426877080000001, + "max": 0.676261042 }, "osprey-arc": { "status": "ok", - "rss": 2981888, - "mean": 1.3009211999999999, - "stddev": 0.01605799073808627, - "min": 1.268521375, - "max": 1.3230813750000001 + "rss": 1589248, + "mean": 0.41672527070000004, + "stddev": 0.005222374606332965, + "min": 0.408999875, + "max": 0.42429441700000003 }, "osprey-gc": { "status": "ok", - "rss": 19103744, - "mean": 4.8061647667, - "stddev": 0.11611339765200909, - "min": 4.628484, - "max": 4.9715053750000004 - } - }, - "coins": { + "rss": 21544960, + "mean": 2.5817890915, + "stddev": 0.07887825386534887, + "min": 2.474969583, + "max": 2.7471665 + }, "rust": { "status": "ok", - "rss": 1589248, - "mean": 0.08257408919444441, - "stddev": 0.0010158890938405999, - "min": 0.0812315, - "max": 0.085808084 + "rss": 1638400, + "mean": 0.0845044118857143, + "stddev": 0.0011511637697473242, + "min": 0.083498583, + "max": 0.090616125 }, "c": { "status": "ok", - "rss": 1474560, - "mean": 0.08095162934210527, - "stddev": 0.006095139130086114, - "min": 0.076753208, - "max": 0.098786916 + "rss": 1523712, + "mean": 0.07980781421621622, + "stddev": 0.0013742166511847588, + "min": 0.078171666, + "max": 0.085285625 }, "csharp": { "status": "ok", - "rss": 7143424, - "mean": 0.10159850713793103, - "stddev": 0.00083632737637759, - "min": 0.100278458, - "max": 0.10323950000000001 + "rss": 7176192, + "mean": 0.10436206542857143, + "stddev": 0.00143215686866523, + "min": 0.10263554200000001, + "max": 0.10946433300000001 }, "dart": { "status": "ok", - "rss": 14581760, - "mean": 0.12227979166666668, - "stddev": 0.0017976053122630944, - "min": 0.11922170800000001, - "max": 0.12810612500000002 + "rss": 14598144, + "mean": 0.12598623958333335, + "stddev": 0.0014552558747334009, + "min": 0.12268695800000001, + "max": 0.128287708 }, "ocaml": { "status": "ok", - "rss": 2326528, - "mean": 0.10049252516666668, - "stddev": 0.0013205633395921216, - "min": 0.09845075, - "max": 0.10549325000000001 + "rss": 2375680, + "mean": 0.1032680603448276, + "stddev": 0.001135403343333116, + "min": 0.10071091700000001, + "max": 0.106182042 }, "haskell": { "status": "ok", - "rss": 11616256, - "mean": 0.05385060548437498, - "stddev": 0.004268713430991334, - "min": 0.046209625000000004, - "max": 0.060093708 + "rss": 11665408, + "mean": 0.05226684465454547, + "stddev": 0.0027690971125920332, + "min": 0.047658250000000006, + "max": 0.06353391700000001 }, - "rust-wasm": { + "osprey-wasm": { "status": "ok", "rss": 0, - "mean": 0.11078164192592592, - "stddev": 0.0017354581028476402, - "min": 0.10784995900000001, - "max": 0.11616433300000001 + "mean": 0.46653334170000005, + "stddev": 0.007839553564626867, + "min": 0.45725254200000004, + "max": 0.47703150000000005 }, + "rust-wasm": { + "status": "ok", + "rss": 0, + "mean": 0.1140096297777778, + "stddev": 0.001736201268221522, + "min": 0.11080395800000001, + "max": 0.116794958 + } + }, + "collatz": { "osprey": { "status": "ok", - "rss": 1437876224, - "mean": 0.6114326877, - "stddev": 0.016850234777748947, - "min": 0.5938914590000001, - "max": 0.64999925 + "rss": 232554496, + "mean": 0.5169422832999999, + "stddev": 0.013790705355969511, + "min": 0.49309395800000005, + "max": 0.538425791 }, "osprey-arc": { "status": "ok", - "rss": 1556480, - "mean": 0.5735767667, - "stddev": 0.006836440040949834, - "min": 0.564006, - "max": 0.589324625 + "rss": 1605632, + "mean": 0.3437300833, + "stddev": 0.003708562904779964, + "min": 0.338606208, + "max": 0.34979862500000003 }, "osprey-gc": { "status": "ok", - "rss": 20037632, - "mean": 3.4439853582000004, - "stddev": 0.20380069881407306, - "min": 3.243480292, - "max": 3.734931875 - } - }, - "collatz": { + "rss": 19415040, + "mean": 2.162322975, + "stddev": 0.055994097289710616, + "min": 2.108872416, + "max": 2.313716291 + }, "rust": { "status": "ok", - "rss": 1605632, - "mean": 0.012998211913636367, - "stddev": 0.0012499878551189905, - "min": 0.012334583000000001, - "max": 0.025512917000000003 + "rss": 1654784, + "mean": 0.013387275982456143, + "stddev": 0.00043979495650019006, + "min": 0.012649708, + "max": 0.017652125 }, "c": { "status": "ok", - "rss": 1441792, - "mean": 0.01044645659385666, - "stddev": 0.0006114763245342595, - "min": 0.009843041, - "max": 0.019331375 + "rss": 1490944, + "mean": 0.010798554530249114, + "stddev": 0.00021295594782420887, + "min": 0.010163416, + "max": 0.011506417000000001 }, "csharp": { "status": "ok", - "rss": 7159808, - "mean": 0.05886338461538464, - "stddev": 0.004283721587421427, - "min": 0.056448000000000005, - "max": 0.083978917 + "rss": 7225344, + "mean": 0.05926145334000001, + "stddev": 0.001024858648299356, + "min": 0.058144084000000006, + "max": 0.065518542 }, "dart": { "status": "ok", - "rss": 14581760, - "mean": 0.06748086456818182, - "stddev": 0.0005848430841308979, - "min": 0.066316125, - "max": 0.069328208 + "rss": 14712832, + "mean": 0.07268866675609757, + "stddev": 0.01115788207388215, + "min": 0.068631, + "max": 0.13992400000000002 }, "ocaml": { "status": "ok", - "rss": 2310144, - "mean": 0.06012169840000001, - "stddev": 0.0023093676497183374, - "min": 0.058078667, - "max": 0.06966204100000001 + "rss": 2375680, + "mean": 0.06455284497222222, + "stddev": 0.009234867279824302, + "min": 0.060400333, + "max": 0.0982215 }, "haskell": { "status": "ok", - "rss": 11616256, - "mean": 0.039342258041095896, - "stddev": 0.005359452472367038, - "min": 0.032010500000000004, - "max": 0.047150166 + "rss": 11681792, + "mean": 0.040156224081081084, + "stddev": 0.001340679646629038, + "min": 0.037041250000000005, + "max": 0.042618625 }, - "rust-wasm": { + "osprey-wasm": { "status": "ok", "rss": 0, - "mean": 0.02459825131451613, - "stddev": 0.0006736481951608612, - "min": 0.02330025, - "max": 0.029071375000000003 + "mean": 0.3803143124, + "stddev": 0.010176944958534129, + "min": 0.35233762500000004, + "max": 0.388013 }, + "rust-wasm": { + "status": "ok", + "rss": 0, + "mean": 0.025428249705882332, + "stddev": 0.000401752759024316, + "min": 0.024446292, + "max": 0.026672750000000002 + } + }, + "coprime": { "osprey": { "status": "ok", - "rss": 1155743744, - "mean": 0.48021789989999997, - "stddev": 0.00672775041813407, - "min": 0.47384533300000004, - "max": 0.497693708 + "rss": 1540096, + "mean": 0.18968425006666667, + "stddev": 0.007622881273645897, + "min": 0.17906275000000002, + "max": 0.21091625 }, "osprey-arc": { "status": "ok", - "rss": 1540096, - "mean": 0.46394785830000007, - "stddev": 0.0033620457576257557, - "min": 0.45972425, - "max": 0.469508209 + "rss": 1605632, + "mean": 0.14842462295, + "stddev": 0.0038440441789308923, + "min": 0.14491400000000002, + "max": 0.157992834 }, "osprey-gc": { "status": "ok", - "rss": 21594112, - "mean": 2.6689815624, - "stddev": 0.07302402682223547, - "min": 2.60189175, - "max": 2.812154375 - } - }, - "coprime": { + "rss": 19562496, + "mean": 0.7033068085000002, + "stddev": 0.28444086452221645, + "min": 0.49116325000000005, + "max": 1.262579542 + }, "rust": { "status": "ok", - "rss": 1589248, - "mean": 0.06566344302173913, - "stddev": 0.0024540571130502817, - "min": 0.06400183300000001, - "max": 0.079053 + "rss": 1638400, + "mean": 0.06638105186666668, + "stddev": 0.0008134717853245267, + "min": 0.065019583, + "max": 0.070086459 }, "c": { "status": "ok", - "rss": 1458176, - "mean": 0.06370379610638298, - "stddev": 0.0004936447065436592, - "min": 0.06293612500000001, - "max": 0.06573025 + "rss": 1507328, + "mean": 0.0650176601956522, + "stddev": 0.0010268040139740523, + "min": 0.063728, + "max": 0.067857584 }, "csharp": { "status": "ok", - "rss": 7159808, - "mean": 0.07816290894736842, - "stddev": 0.0023460697649299177, - "min": 0.074818375, - "max": 0.08521029100000001 + "rss": 7176192, + "mean": 0.08050876399999998, + "stddev": 0.0018821397035072606, + "min": 0.076998667, + "max": 0.08391575000000001 }, "dart": { "status": "ok", - "rss": 14548992, - "mean": 0.11317230248148148, - "stddev": 0.010146650208284713, - "min": 0.105589334, - "max": 0.141202209 + "rss": 14647296, + "mean": 0.11159666196296299, + "stddev": 0.0021251538302284674, + "min": 0.10879354200000001, + "max": 0.119872 }, "ocaml": { "status": "ok", - "rss": 2326528, - "mean": 0.0907261352121212, - "stddev": 0.0007173611177895247, - "min": 0.089494667, - "max": 0.09209362500000001 + "rss": 2375680, + "mean": 0.11939039351851852, + "stddev": 0.05063322571330749, + "min": 0.092244583, + "max": 0.326904375 }, "haskell": { "status": "ok", - "rss": 11616256, - "mean": 0.1057096965357143, - "stddev": 0.004474232563715916, - "min": 0.09970437500000001, - "max": 0.11375820900000001 + "rss": 11681792, + "mean": 0.22033766040000002, + "stddev": 0.05682870056443925, + "min": 0.145737166, + "max": 0.310412416 }, - "rust-wasm": { + "osprey-wasm": { "status": "ok", "rss": 0, - "mean": 0.0772853235, - "stddev": 0.0004942422530987155, - "min": 0.07664116700000001, - "max": 0.07881500000000001 + "mean": 0.2964668623000001, + "stddev": 0.08806832287891106, + "min": 0.188067, + "max": 0.50987375 }, + "rust-wasm": { + "status": "ok", + "rss": 0, + "mean": 0.16329303755000002, + "stddev": 0.03578338971243287, + "min": 0.11621995900000001, + "max": 0.22057158300000002 + } + }, + "digitsum": { "osprey": { "status": "ok", - "rss": 1040334848, - "mean": 0.390137846, - "stddev": 0.00545764009829277, - "min": 0.381848625, - "max": 0.39826041700000003 + "rss": 351404032, + "mean": 0.6868699084000001, + "stddev": 0.04287172572126729, + "min": 0.631650459, + "max": 0.7608216670000001 }, "osprey-arc": { "status": "ok", - "rss": 1540096, - "mean": 0.373116804, - "stddev": 0.0034224510965095304, - "min": 0.36920004100000003, - "max": 0.378744375 + "rss": 1589248, + "mean": 0.39785358759999995, + "stddev": 0.03704009496065983, + "min": 0.33786345900000003, + "max": 0.456918584 }, "osprey-gc": { "status": "ok", - "rss": 19513344, - "mean": 2.2889062082, - "stddev": 0.03320976588523099, - "min": 2.246980625, - "max": 2.360280916 - } - }, - "digitsum": { + "rss": 23117824, + "mean": 4.6291250335, + "stddev": 1.2397568398894363, + "min": 3.556016625, + "max": 7.253373292 + }, "rust": { "status": "ok", - "rss": 1605632, - "mean": 0.0056644806652542375, - "stddev": 0.0006048329932653483, - "min": 0.00517525, - "max": 0.011000458000000001 + "rss": 1654784, + "mean": 0.0061150652584493, + "stddev": 0.0005349366989917296, + "min": 0.005615042000000001, + "max": 0.012447583 }, "c": { "status": "ok", - "rss": 1458176, - "mean": 0.0055714575724637675, - "stddev": 0.00027383669939637324, - "min": 0.005109583, - "max": 0.00956425 + "rss": 1507328, + "mean": 0.006074728629166668, + "stddev": 0.00044522769860402676, + "min": 0.005665334, + "max": 0.012052959 }, "csharp": { "status": "ok", - "rss": 7143424, - "mean": 0.016389021483695646, - "stddev": 0.00038719781687823035, - "min": 0.015695916, - "max": 0.018449291 + "rss": 7192576, + "mean": 0.021225391023668647, + "stddev": 0.00347726351888477, + "min": 0.016784208000000002, + "max": 0.044878542 }, "dart": { "status": "ok", - "rss": 14548992, - "mean": 0.029150055805825244, - "stddev": 0.0018720284116632872, - "min": 0.027778792, - "max": 0.044238291000000006 + "rss": 14647296, + "mean": 0.03276187038043478, + "stddev": 0.004851440947493856, + "min": 0.029389125000000002, + "max": 0.068537791 }, "ocaml": { "status": "ok", - "rss": 2326528, - "mean": 0.0187444790754717, - "stddev": 0.0004080229868973404, - "min": 0.018236333, - "max": 0.022929500000000002 + "rss": 2375680, + "mean": 0.019540921758620686, + "stddev": 0.0012077972277036984, + "min": 0.018457542, + "max": 0.028021291 }, "haskell": { "status": "ok", - "rss": 11599872, - "mean": 0.032285782032967045, - "stddev": 0.0029869211514407805, - "min": 0.026689625, - "max": 0.042387542 + "rss": 11665408, + "mean": 0.029434408742857153, + "stddev": 0.002896327659697141, + "min": 0.026709667000000003, + "max": 0.040200833000000005 }, - "rust-wasm": { + "osprey-wasm": { "status": "ok", "rss": 0, - "mean": 0.01908640507096774, - "stddev": 0.000603050071550524, - "min": 0.017606042000000002, - "max": 0.022009125 + "mean": 0.2799603166, + "stddev": 0.0021985694889920457, + "min": 0.277658958, + "max": 0.28402525 }, + "rust-wasm": { + "status": "ok", + "rss": 0, + "mean": 0.018819117038216555, + "stddev": 0.0014288175873372235, + "min": 0.017816500000000002, + "max": 0.034545792 + } + }, + "exprtree": { "osprey": { "status": "ok", - "rss": 1115258880, - "mean": 0.40829771270000004, - "stddev": 0.003931430202687569, - "min": 0.401932875, - "max": 0.414786417 + "rss": 9551872, + "mean": 0.04639940952857146, + "stddev": 0.006565826217877867, + "min": 0.0391345, + "max": 0.07766041600000001 }, "osprey-arc": { "status": "ok", - "rss": 1523712, - "mean": 0.39770332920000007, - "stddev": 0.009091025450032063, - "min": 0.38357079200000005, - "max": 0.409295583 + "rss": 3588096, + "mean": 0.02808243907692306, + "stddev": 0.0013536385943329786, + "min": 0.026424542000000002, + "max": 0.039513333000000005 }, "osprey-gc": { "status": "ok", - "rss": 19759104, - "mean": 2.4584255498000003, - "stddev": 0.03416635791302194, - "min": 2.412894291, - "max": 2.514155916 - } - }, - "exprtree": { + "rss": 19431424, + "mean": 0.14887335894444448, + "stddev": 0.006688579189485409, + "min": 0.136912375, + "max": 0.16462520900000002 + }, "rust": { "status": "ok", - "rss": 2768896, - "mean": 0.010827280024999993, - "stddev": 0.00039974153318721243, - "min": 0.010235458000000001, - "max": 0.013338958000000001 + "rss": 2801664, + "mean": 0.011055564888475838, + "stddev": 0.001190477724379986, + "min": 0.010010625, + "max": 0.02890175 }, "c": { "status": "ok", - "rss": 11993088, - "mean": 0.006274227775933614, - "stddev": 0.00036957366982882863, - "min": 0.005747792000000001, - "max": 0.0116085 + "rss": 12042240, + "mean": 0.006137397940451746, + "stddev": 0.00023245990574442368, + "min": 0.005666667, + "max": 0.008838125 }, "csharp": { "status": "ok", - "rss": 15925248, - "mean": 0.006545514061810152, - "stddev": 0.0003513326847530027, - "min": 0.005903708000000001, - "max": 0.010394042000000001 + "rss": 15958016, + "mean": 0.007659041112359549, + "stddev": 0.0017523217808740207, + "min": 0.006112167, + "max": 0.021112041 }, "dart": { "status": "ok", - "rss": 23560192, - "mean": 0.014330422873831768, - "stddev": 0.0012088148890255636, - "min": 0.012898125000000002, - "max": 0.025659625000000002 + "rss": 23625728, + "mean": 0.01578685686387435, + "stddev": 0.0030299652925669814, + "min": 0.013268208, + "max": 0.030820917000000003 }, "ocaml": { "status": "ok", - "rss": 6340608, - "mean": 0.005299159833641399, - "stddev": 0.0002316092144091591, - "min": 0.004873000000000001, - "max": 0.007285125000000001 + "rss": 6389760, + "mean": 0.005142559884547072, + "stddev": 0.0002708359127864659, + "min": 0.004780042, + "max": 0.009548917 }, "haskell": { "status": "ok", - "rss": 11894784, - "mean": 0.018107108275449094, - "stddev": 0.001644205808611337, - "min": 0.014470791, - "max": 0.021136583 + "rss": 11943936, + "mean": 0.016315626648044694, + "stddev": 0.0008151585589737162, + "min": 0.013936541, + "max": 0.017602125 }, - "rust-wasm": { + "osprey-wasm": { "status": "ok", "rss": 0, - "mean": 0.020556294219178085, - "stddev": 0.0005417944128814085, - "min": 0.019722792000000003, - "max": 0.024282125 + "mean": 0.033682716222222214, + "stddev": 0.0010037253315625962, + "min": 0.0325755, + "max": 0.039885167 }, + "rust-wasm": { + "status": "ok", + "rss": 0, + "mean": 0.020427309551020414, + "stddev": 0.0004232256081473258, + "min": 0.01953425, + "max": 0.022182084 + } + }, + "factorial": { "osprey": { "status": "ok", - "rss": 114753536, - "mean": 0.044387047161764726, - "stddev": 0.0007467193816726605, - "min": 0.042941708, - "max": 0.047214417 + "rss": 1540096, + "mean": 0.03578326189285714, + "stddev": 0.001513206917229309, + "min": 0.034964167000000004, + "max": 0.044312250000000004 }, "osprey-arc": { "status": "ok", - "rss": 3522560, - "mean": 0.04789132474603175, - "stddev": 0.0011334056089554083, - "min": 0.045801791, - "max": 0.05135337500000001 + "rss": 1572864, + "mean": 0.03550394748809524, + "stddev": 0.00032732469364463455, + "min": 0.035105250000000005, + "max": 0.037037125000000004 }, "osprey-gc": { "status": "ok", - "rss": 19431424, - "mean": 0.2811709585, - "stddev": 0.006739000683151438, - "min": 0.27331508400000004, - "max": 0.29421575 - } - }, - "factorial": { + "rss": 1572864, + "mean": 0.03538517159523808, + "stddev": 0.00015988288843936293, + "min": 0.034926458, + "max": 0.035866083 + }, "rust": { "status": "ok", - "rss": 1605632, - "mean": 0.03552227971428571, - "stddev": 0.00025707397070519274, - "min": 0.034823958, - "max": 0.036091000000000005 + "rss": 1654784, + "mean": 0.03558819838095238, + "stddev": 0.0006344863207399686, + "min": 0.034857167, + "max": 0.039547459 }, "c": { "status": "ok", - "rss": 1441792, - "mean": 0.03540608338554218, - "stddev": 0.0007251188198172362, - "min": 0.034834333, - "max": 0.03985975 + "rss": 1490944, + "mean": 0.035272794623529426, + "stddev": 0.00035840252177813666, + "min": 0.034439791000000004, + "max": 0.03796 }, "csharp": { "status": "ok", "rss": 7159808, - "mean": 0.037176412525, - "stddev": 0.0003850360558335376, - "min": 0.03658725, - "max": 0.039014792 + "mean": 0.03744076252500001, + "stddev": 0.0004378210813837081, + "min": 0.036860791000000004, + "max": 0.040262583000000005 }, "dart": { "status": "ok", - "rss": 14499840, - "mean": 0.051676922571428585, - "stddev": 0.0011957507100507473, - "min": 0.050336458, - "max": 0.059105667 + "rss": 14565376, + "mean": 0.05123341292982457, + "stddev": 0.0011264072968066089, + "min": 0.050052791000000006, + "max": 0.058936833 }, "ocaml": { "status": "ok", - "rss": 2310144, - "mean": 0.048736652999999984, - "stddev": 0.0008640425810047979, - "min": 0.047989667, - "max": 0.054702 + "rss": 2392064, + "mean": 0.048704362854838694, + "stddev": 0.0005192495393882533, + "min": 0.047828083, + "max": 0.050875166000000006 }, "haskell": { "status": "ok", - "rss": 11632640, - "mean": 0.05739876552542372, - "stddev": 0.0033447143635890967, - "min": 0.050183542000000005, - "max": 0.064451666 + "rss": 11681792, + "mean": 0.053541213571428554, + "stddev": 0.003052632923092408, + "min": 0.050463083000000006, + "max": 0.067079833 }, - "rust-wasm": { + "osprey-wasm": { "status": "ok", "rss": 0, - "mean": 0.048635114754098374, - "stddev": 0.0010682380897560505, - "min": 0.047196958000000004, - "max": 0.055848458000000004 + "mean": 0.044685138059701486, + "stddev": 0.0005962561641262941, + "min": 0.043890584, + "max": 0.047516042 }, + "rust-wasm": { + "status": "ok", + "rss": 0, + "mean": 0.0485607215, + "stddev": 0.0007485810418462227, + "min": 0.047235959, + "max": 0.050907208 + } + }, + "fib": { "osprey": { "status": "ok", - "rss": 644055040, - "mean": 0.23723847225000003, - "stddev": 0.002568513948559649, - "min": 0.23268225, - "max": 0.23985275 + "rss": 1572864, + "mean": 1.0967378082, + "stddev": 0.06097487773372059, + "min": 1.024021583, + "max": 1.194007375 }, "osprey-arc": { "status": "ok", - "rss": 1523712, - "mean": 0.22449130769230768, - "stddev": 0.00527303762463472, - "min": 0.217360875, - "max": 0.237485792 + "rss": 1605632, + "mean": 0.6005175457, + "stddev": 0.014154781532592852, + "min": 0.5788255, + "max": 0.6171867910000001 }, "osprey-gc": { "status": "ok", - "rss": 20578304, - "mean": 1.420570575, - "stddev": 0.020475228067282535, - "min": 1.398616625, - "max": 1.453321459 - } - }, - "fib": { + "rss": 23527424, + "mean": 4.502327116800001, + "stddev": 0.20244397271565726, + "min": 4.241174167, + "max": 4.866583042 + }, "rust": { "status": "ok", - "rss": 1605632, - "mean": 0.017581413574712646, - "stddev": 0.00043395038556468316, - "min": 0.016853166000000003, - "max": 0.021091125000000002 + "rss": 1654784, + "mean": 0.022749431952000007, + "stddev": 0.002219661298865001, + "min": 0.018210625, + "max": 0.031330292 }, "c": { "status": "ok", - "rss": 1441792, - "mean": 0.018446179095808396, - "stddev": 0.0025683387245724154, - "min": 0.016893458, - "max": 0.038403625000000004 + "rss": 1490944, + "mean": 0.02336248195762711, + "stddev": 0.0031800304251197622, + "min": 0.018520625000000002, + "max": 0.044872291 }, "csharp": { "status": "ok", - "rss": 7159808, - "mean": 0.03664424412941177, - "stddev": 0.0008690054315977955, - "min": 0.035274, - "max": 0.04046625 + "rss": 7176192, + "mean": 0.04326382743750002, + "stddev": 0.004716196922175253, + "min": 0.037600917000000005, + "max": 0.066906666 }, "dart": { "status": "ok", - "rss": 14532608, - "mean": 0.0522060036491228, - "stddev": 0.0014728759154136598, - "min": 0.050650083000000005, - "max": 0.061345459000000005 + "rss": 14598144, + "mean": 0.05979236232608694, + "stddev": 0.0057044496996698215, + "min": 0.055473542, + "max": 0.09014691600000001 }, "ocaml": { "status": "ok", - "rss": 2326528, - "mean": 0.024231674146341465, - "stddev": 0.0004529051543624888, - "min": 0.023478125000000002, - "max": 0.025637458000000002 + "rss": 2359296, + "mean": 0.0295490298367347, + "stddev": 0.0027085029897803603, + "min": 0.023847959000000002, + "max": 0.044013042 }, "haskell": { "status": "ok", - "rss": 11632640, - "mean": 0.04797363056603773, - "stddev": 0.004271504455846574, - "min": 0.041552916, - "max": 0.057915334000000006 + "rss": 11698176, + "mean": 0.056461275943396234, + "stddev": 0.005606782591697133, + "min": 0.042979500000000004, + "max": 0.08237404200000001 }, - "rust-wasm": { + "osprey-wasm": { "status": "ok", "rss": 0, - "mean": 0.03725080911392406, - "stddev": 0.0009369079515308684, - "min": 0.035983, - "max": 0.042810417 + "mean": 0.6849400541, + "stddev": 0.04374474425109943, + "min": 0.636344291, + "max": 0.7881401250000001 }, + "rust-wasm": { + "status": "ok", + "rss": 0, + "mean": 0.04944626785245901, + "stddev": 0.0054906045597176555, + "min": 0.038254250000000004, + "max": 0.072645334 + } + }, + "gcdsum": { "osprey": { "status": "ok", - "rss": 1440481280, - "mean": 0.5555568293, - "stddev": 0.007364569702087808, - "min": 0.543532542, - "max": 0.564626625 + "rss": 1556480, + "mean": 0.13393916417647062, + "stddev": 0.011635362320979307, + "min": 0.12511929200000002, + "max": 0.170615459 }, "osprey-arc": { "status": "ok", - "rss": 1523712, - "mean": 0.5359994832, - "stddev": 0.006936479775792618, - "min": 0.523771208, - "max": 0.5489312080000001 + "rss": 1589248, + "mean": 0.12006210246153848, + "stddev": 0.009691848344394014, + "min": 0.11051329100000001, + "max": 0.14251491700000002 }, "osprey-gc": { "status": "ok", - "rss": 19513344, - "mean": 3.1710282166, - "stddev": 0.07265083420146609, - "min": 3.083246, - "max": 3.284425583 - } - }, - "gcdsum": { + "rss": 23396352, + "mean": 0.24119167809090916, + "stddev": 0.009572090531204055, + "min": 0.232937791, + "max": 0.2619265 + }, "rust": { "status": "ok", - "rss": 1605632, - "mean": 0.0795029144054054, - "stddev": 0.0027988867165444297, - "min": 0.07809795900000001, - "max": 0.09552525 + "rss": 1654784, + "mean": 0.0860667418611111, + "stddev": 0.005821787114737851, + "min": 0.08053083300000001, + "max": 0.10663454200000001 }, "c": { "status": "ok", - "rss": 1458176, - "mean": 0.07945484240540542, - "stddev": 0.0010341578036696627, - "min": 0.078521167, - "max": 0.08525825000000001 + "rss": 1507328, + "mean": 0.08645032862857144, + "stddev": 0.005506866222596087, + "min": 0.08054375000000001, + "max": 0.111463375 }, "csharp": { "status": "ok", - "rss": 7143424, - "mean": 0.08615537126470588, - "stddev": 0.0007135942234458972, - "min": 0.08484108400000001, - "max": 0.08744175 + "rss": 7192576, + "mean": 0.09284992328125, + "stddev": 0.0030703698655335974, + "min": 0.08833075, + "max": 0.10354808400000001 }, "dart": { "status": "ok", - "rss": 14467072, - "mean": 0.11049248318518518, - "stddev": 0.0015175748869287365, - "min": 0.10733804200000001, - "max": 0.114217917 + "rss": 14647296, + "mean": 0.12202371680000003, + "stddev": 0.012670853212860841, + "min": 0.11122258400000001, + "max": 0.177581917 }, "ocaml": { "status": "ok", - "rss": 2326528, - "mean": 0.10193025868965519, - "stddev": 0.004403302464260571, - "min": 0.10043025000000001, - "max": 0.12464183300000001 + "rss": 2375680, + "mean": 0.1077045647777778, + "stddev": 0.0036401353980443593, + "min": 0.10303487500000001, + "max": 0.11850033400000001 }, "haskell": { "status": "ok", - "rss": 11616256, - "mean": 0.10648335772413794, - "stddev": 0.005447719275404307, - "min": 0.09803191700000001, - "max": 0.122359042 + "rss": 11665408, + "mean": 0.11499818753846153, + "stddev": 0.007053048654529232, + "min": 0.104426292, + "max": 0.14197616600000001 }, - "rust-wasm": { + "osprey-wasm": { "status": "ok", "rss": 0, - "mean": 0.09212542803030305, - "stddev": 0.0024526354871836128, - "min": 0.08922437500000001, - "max": 0.100523291 + "mean": 0.12651623343478263, + "stddev": 0.007249976095872423, + "min": 0.11556208300000001, + "max": 0.151723708 }, + "rust-wasm": { + "status": "ok", + "rss": 0, + "mean": 0.10432213893333336, + "stddev": 0.006698636894629206, + "min": 0.09856545800000001, + "max": 0.13407470800000001 + } + }, + "hanoi": { "osprey": { "status": "ok", - "rss": 912244736, - "mean": 0.33105869970000007, - "stddev": 0.005447205484370346, - "min": 0.31816966700000004, - "max": 0.337029416 + "rss": 1572864, + "mean": 1.7658339835999999, + "stddev": 0.1061672848861848, + "min": 1.616819417, + "max": 1.969139459 }, "osprey-arc": { "status": "ok", - "rss": 1523712, - "mean": 0.3233511082, - "stddev": 0.004606660362735017, - "min": 0.31658325000000004, - "max": 0.327873375 + "rss": 1589248, + "mean": 0.9792789001, + "stddev": 0.039341067540969624, + "min": 0.920022125, + "max": 1.041917958 }, "osprey-gc": { "status": "ok", - "rss": 19742720, - "mean": 1.9958096540999997, - "stddev": 0.03697976229076407, - "min": 1.9263946660000002, - "max": 2.056321333 - } - }, - "hanoi": { + "rss": 23511040, + "mean": 5.487777683300001, + "stddev": 0.2478329046399615, + "min": 5.249610667, + "max": 6.148424541 + }, "rust": { "status": "ok", - "rss": 1589248, - "mean": 0.03894848526760564, - "stddev": 0.0020196858126145835, - "min": 0.035713292, - "max": 0.049484417 + "rss": 1638400, + "mean": 0.037454780199999996, + "stddev": 0.0013947801368631582, + "min": 0.0355605, + "max": 0.045349708 }, "c": { "status": "ok", - "rss": 1458176, - "mean": 0.04103687717333334, - "stddev": 0.0035816500726185848, - "min": 0.037645708, - "max": 0.055672792000000006 + "rss": 1507328, + "mean": 0.03846204775999999, + "stddev": 0.0010661856496383005, + "min": 0.036305917, + "max": 0.042533208 }, "csharp": { "status": "ok", - "rss": 7127040, - "mean": 0.044943885063291146, - "stddev": 0.008233431507026155, - "min": 0.037204584, - "max": 0.071261083 + "rss": 7159808, + "mean": 0.03873336549333334, + "stddev": 0.002089405447996497, + "min": 0.037109208000000005, + "max": 0.054685875 }, "dart": { "status": "ok", - "rss": 14630912, - "mean": 0.12011186123809527, - "stddev": 0.023236871541913468, - "min": 0.1038285, - "max": 0.192020833 + "rss": 14516224, + "mean": 0.1038988174827586, + "stddev": 0.002485871004786633, + "min": 0.102402583, + "max": 0.11544950000000001 }, "ocaml": { "status": "ok", - "rss": 2326528, - "mean": 0.06279330691836733, - "stddev": 0.0022602365829977834, - "min": 0.059935, - "max": 0.070578625 + "rss": 2375680, + "mean": 0.0628701648478261, + "stddev": 0.0012488367794594732, + "min": 0.061400958000000005, + "max": 0.067673417 }, "haskell": { "status": "ok", - "rss": 11632640, - "mean": 0.05815280124999999, - "stddev": 0.0032032368690027807, - "min": 0.050631042, - "max": 0.064581291 + "rss": 11698176, + "mean": 0.05436641583636363, + "stddev": 0.0038500417978741906, + "min": 0.050348375, + "max": 0.06518979100000001 }, - "rust-wasm": { + "osprey-wasm": { "status": "ok", "rss": 0, - "mean": 0.053146982160714284, - "stddev": 0.0011110850704951075, - "min": 0.051489167, - "max": 0.056413916 + "mean": 0.7660782916000001, + "stddev": 0.006558170464678451, + "min": 0.7523724580000001, + "max": 0.77336225 }, + "rust-wasm": { + "status": "ok", + "rss": 0, + "mean": 0.05225895687499999, + "stddev": 0.0014221556941517023, + "min": 0.050688708000000006, + "max": 0.060885542 + } + }, + "isqrt": { "osprey": { "status": "ok", - "rss": 3235397632, - "mean": 1.2541156459, - "stddev": 0.01987384779414938, - "min": 1.231548084, - "max": 1.293495917 + "rss": 816939008, + "mean": 0.5638269001, + "stddev": 0.016415897979933106, + "min": 0.536789084, + "max": 0.586881667 }, "osprey-arc": { "status": "ok", - "rss": 1540096, - "mean": 1.2442459957, - "stddev": 0.017786828624979177, - "min": 1.209263208, - "max": 1.280249333 + "rss": 1589248, + "mean": 0.41425402930000005, + "stddev": 0.0023824435854444877, + "min": 0.40968625000000003, + "max": 0.41688154200000005 }, "osprey-gc": { "status": "ok", - "rss": 21594112, - "mean": 7.288645320799999, - "stddev": 0.10494937221685548, - "min": 7.14649925, - "max": 7.459104458 - } - }, - "isqrt": { + "rss": 21659648, + "mean": 3.0092842791, + "stddev": 0.09720068640314258, + "min": 2.880668625, + "max": 3.178893 + }, "rust": { "status": "ok", - "rss": 1605632, - "mean": 0.011221936762452102, - "stddev": 0.0003955225766759003, - "min": 0.010721625, - "max": 0.015431333 + "rss": 1654784, + "mean": 0.010861193066176474, + "stddev": 0.00012183835455662447, + "min": 0.010525208000000001, + "max": 0.011347459 }, "c": { "status": "ok", - "rss": 1458176, - "mean": 0.010779150633093527, - "stddev": 0.0008439144238814017, - "min": 0.010136583000000001, - "max": 0.017985708 + "rss": 1507328, + "mean": 0.010588533364864865, + "stddev": 0.000919878111838731, + "min": 0.010123833, + "max": 0.018722208 }, "csharp": { "status": "ok", "rss": 7176192, - "mean": 0.017505717011299434, - "stddev": 0.000931748159848434, - "min": 0.015604917000000001, - "max": 0.024272458 + "mean": 0.017082089059880234, + "stddev": 0.0007614041209117574, + "min": 0.015442458000000001, + "max": 0.018597333 }, "dart": { "status": "ok", - "rss": 14598144, - "mean": 0.034011108218390804, - "stddev": 0.0028466719529610706, - "min": 0.031999792, - "max": 0.05374475 + "rss": 14565376, + "mean": 0.0325380707173913, + "stddev": 0.0003215396369764237, + "min": 0.031845584, + "max": 0.033462041000000005 }, "ocaml": { "status": "ok", - "rss": 2326528, - "mean": 0.02125999680555556, - "stddev": 0.003767305210802287, - "min": 0.020396458000000003, - "max": 0.06296550000000001 + "rss": 2375680, + "mean": 0.02057126590972221, + "stddev": 0.00026135967165082194, + "min": 0.020127000000000003, + "max": 0.022644042000000003 }, "haskell": { "status": "ok", - "rss": 11616256, - "mean": 0.04525433332857141, - "stddev": 0.0028664473116191817, - "min": 0.039173583000000005, - "max": 0.058176084 + "rss": 11665408, + "mean": 0.0409927484, + "stddev": 0.001248487852593353, + "min": 0.037094792, + "max": 0.044433541 }, - "rust-wasm": { + "osprey-wasm": { "status": "ok", "rss": 0, - "mean": 0.023408056400000002, - "stddev": 0.0008756533189253798, - "min": 0.02181375, - "max": 0.029699875 + "mean": 0.4128552541, + "stddev": 0.00936579835004184, + "min": 0.39674904200000005, + "max": 0.422523833 }, + "rust-wasm": { + "status": "ok", + "rss": 0, + "mean": 0.022863915298387095, + "stddev": 0.0006013746779625568, + "min": 0.02163125, + "max": 0.024029042 + } + }, + "josephus": { "osprey": { "status": "ok", - "rss": 1256669184, - "mean": 0.4452364291000001, - "stddev": 0.004841701417112779, - "min": 0.43806075000000005, - "max": 0.45286800000000005 + "rss": 1556480, + "mean": 0.38011732090000006, + "stddev": 0.020362500359764297, + "min": 0.346817417, + "max": 0.40160879200000005 }, "osprey-arc": { "status": "ok", - "rss": 1540096, - "mean": 0.44429240830000005, - "stddev": 0.007358797696764945, - "min": 0.435011417, - "max": 0.45452775 + "rss": 1589248, + "mean": 0.22222674684615384, + "stddev": 0.003443769347644424, + "min": 0.21822966700000002, + "max": 0.22924487500000001 }, "osprey-gc": { "status": "ok", - "rss": 20021248, - "mean": 2.7168718583, - "stddev": 0.029170105451374013, - "min": 2.674621125, - "max": 2.760632083 - } - }, - "josephus": { + "rss": 19546112, + "mean": 1.5125415002000002, + "stddev": 0.033063200417093846, + "min": 1.450689791, + "max": 1.551317167 + }, "rust": { "status": "ok", - "rss": 1605632, - "mean": 0.03353150856818183, - "stddev": 0.0002452983254385115, - "min": 0.032973417000000005, - "max": 0.034261708 + "rss": 1654784, + "mean": 0.03378836739772728, + "stddev": 0.0012432857417046036, + "min": 0.032928416, + "max": 0.044432458 }, "c": { "status": "ok", - "rss": 1458176, - "mean": 0.03343088463736266, - "stddev": 0.0005534429220089564, - "min": 0.032749125000000004, - "max": 0.0375395 + "rss": 1507328, + "mean": 0.03338863751111111, + "stddev": 0.00041959660105285256, + "min": 0.032819166000000004, + "max": 0.036558417 }, "csharp": { "status": "ok", "rss": 7159808, - "mean": 0.03529610681176471, - "stddev": 0.0003087187230584585, - "min": 0.034473917, - "max": 0.036309084000000005 + "mean": 0.035859348190476203, + "stddev": 0.0020030351056426186, + "min": 0.034856041000000004, + "max": 0.053671917000000006 }, "dart": { "status": "ok", - "rss": 14598144, - "mean": 0.04324393366197184, - "stddev": 0.0027295495420667963, - "min": 0.041561375000000005, - "max": 0.057981209000000006 + "rss": 14467072, + "mean": 0.04204183916901408, + "stddev": 0.0010148233670623813, + "min": 0.041225584, + "max": 0.048509000000000004 }, "ocaml": { "status": "ok", - "rss": 2342912, - "mean": 0.0415584177361111, - "stddev": 0.0003659726713168462, - "min": 0.040970083000000004, - "max": 0.043211959 + "rss": 2375680, + "mean": 0.04198019305633802, + "stddev": 0.0008071680743438911, + "min": 0.041222791, + "max": 0.046650708000000006 }, "haskell": { "status": "ok", - "rss": 11632640, - "mean": 0.045739036116666666, - "stddev": 0.004736653181787487, - "min": 0.040007916000000004, - "max": 0.052652417 + "rss": 11681792, + "mean": 0.044499815154929574, + "stddev": 0.004547499541831843, + "min": 0.04031425, + "max": 0.052819500000000005 }, - "rust-wasm": { + "osprey-wasm": { "status": "ok", "rss": 0, - "mean": 0.045317588865671665, - "stddev": 0.005667616629265701, - "min": 0.043209500000000005, - "max": 0.090193625 + "mean": 0.24372987183333336, + "stddev": 0.012623585703983087, + "min": 0.22283012500000002, + "max": 0.275226167 }, + "rust-wasm": { + "status": "ok", + "rss": 0, + "mean": 0.044423656312500004, + "stddev": 0.000425759992644409, + "min": 0.043652042, + "max": 0.046727042 + } + }, + "listops": { "osprey": { "status": "ok", - "rss": 644087808, - "mean": 0.23231849369230773, - "stddev": 0.004529763027571093, - "min": 0.22465045800000003, - "max": 0.24075237500000002 + "rss": 15138816, + "mean": 0.007195345255754477, + "stddev": 0.0003373199330192691, + "min": 0.006650292, + "max": 0.011863666 }, "osprey-arc": { "status": "ok", - "rss": 1556480, - "mean": 0.22558221469230766, - "stddev": 0.004276809633841102, - "min": 0.21952716700000002, - "max": 0.23671170900000002 + "rss": 2195456, + "mean": 0.006149954807851241, + "stddev": 0.0002087478684496479, + "min": 0.005743750000000001, + "max": 0.007855334 }, "osprey-gc": { "status": "ok", - "rss": 19496960, - "mean": 1.4126058084, - "stddev": 0.03284989451376663, - "min": 1.377491208, - "max": 1.468826042 - } - }, - "listops": { + "rss": 13484032, + "mean": 0.0174095495698324, + "stddev": 0.0005431016089357968, + "min": 0.015907708, + "max": 0.018699333000000002 + }, "rust": { "status": "ok", - "rss": 1687552, - "mean": 0.0016019486593659919, - "stddev": 0.00021737134409098244, - "min": 0.0012707080000000002, - "max": 0.004036709 + "rss": 1736704, + "mean": 0.0014722135077399384, + "stddev": 0.00010530293437184364, + "min": 0.001311459, + "max": 0.002418417 }, "c": { "status": "ok", - "rss": 1474560, - "mean": 0.0013816131150081578, - "stddev": 0.0001569179926477613, - "min": 0.0011243750000000002, - "max": 0.0036863340000000003 + "rss": 1523712, + "mean": 0.0012927572735462723, + "stddev": 8.914914674143355e-05, + "min": 0.0011575420000000001, + "max": 0.001861791 }, "csharp": { "status": "ok", - "rss": 7389184, - "mean": 0.0032475916484607805, - "stddev": 0.00045763047551760223, - "min": 0.002569708, - "max": 0.01013375 + "rss": 7438336, + "mean": 0.0032745058003913904, + "stddev": 0.00030524484701306064, + "min": 0.002847959, + "max": 0.007146667000000001 }, "dart": { "status": "ok", - "rss": 15007744, - "mean": 0.011135839333333331, - "stddev": 0.0005856924657826856, - "min": 0.009811209000000001, - "max": 0.015125500000000002 + "rss": 14991360, + "mean": 0.010755559032388671, + "stddev": 0.000520560748797698, + "min": 0.009787084000000001, + "max": 0.014714000000000001 }, "ocaml": { "status": "ok", - "rss": 2654208, - "mean": 0.0022145197398316966, - "stddev": 0.00020627749017411548, - "min": 0.0018463750000000001, - "max": 0.005421625 + "rss": 2703360, + "mean": 0.002236547548484847, + "stddev": 0.0002989270122500942, + "min": 0.00191025, + "max": 0.00803675 }, "haskell": { "status": "ok", - "rss": 11862016, - "mean": 0.01659073348044694, - "stddev": 0.0008740296526145366, - "min": 0.014569958000000001, - "max": 0.017929708000000003 + "rss": 11911168, + "mean": 0.01657285047368422, + "stddev": 0.0007825007369471431, + "min": 0.014460584, + "max": 0.019387333 }, - "rust-wasm": { + "osprey-wasm": { "status": "ok", "rss": 0, - "mean": 0.012750923216101693, - "stddev": 0.0006199062734519334, - "min": 0.011835958, - "max": 0.01807475 + "mean": 0.013442210361607141, + "stddev": 0.0005032358386621333, + "min": 0.012622125000000001, + "max": 0.016902375 }, + "rust-wasm": { + "status": "ok", + "rss": 0, + "mean": 0.01251011879574468, + "stddev": 0.00030477305900828214, + "min": 0.011572708000000001, + "max": 0.013388333 + } + }, + "mutual": { "osprey": { "status": "ok", - "rss": 23314432, - "mean": 0.0068688803945578195, - "stddev": 0.00038134244730743145, - "min": 0.0063269170000000005, - "max": 0.009816625 + "rss": 1540096, + "mean": 0.019272592408163276, + "stddev": 0.0011811274651792457, + "min": 0.017210042000000002, + "max": 0.024849167000000002 }, "osprey-arc": { "status": "ok", - "rss": 2146304, - "mean": 0.007407462724880381, - "stddev": 0.00035197314032605736, - "min": 0.006872958, - "max": 0.012674042 + "rss": 1589248, + "mean": 0.0182584760472973, + "stddev": 0.0012776150584631455, + "min": 0.016297125000000003, + "max": 0.020501166 }, "osprey-gc": { "status": "ok", - "rss": 14680064, - "mean": 0.024367843860655745, - "stddev": 0.001554395151235203, - "min": 0.021817000000000003, - "max": 0.034591500000000004 - } - }, - "mutual": { + "rss": 7634944, + "mean": 0.019702362901234567, + "stddev": 0.0011023657058335118, + "min": 0.018030167, + "max": 0.021830917000000002 + }, "rust": { "status": "ok", - "rss": 1589248, - "mean": 0.01321096566359447, - "stddev": 0.0007173372291972909, - "min": 0.012475875, - "max": 0.02078475 + "rss": 1638400, + "mean": 0.01308008149115045, + "stddev": 0.0003247548414876844, + "min": 0.012276750000000001, + "max": 0.015026583000000001 }, "c": { "status": "ok", - "rss": 1441792, - "mean": 0.012888910734513273, - "stddev": 0.0004238730879176719, - "min": 0.012046417, - "max": 0.014517750000000001 + "rss": 1490944, + "mean": 0.012879709545833324, + "stddev": 0.00038915154228777216, + "min": 0.01214225, + "max": 0.014114833 }, "csharp": { "status": "ok", - "rss": 7143424, - "mean": 0.021601226131034483, - "stddev": 0.0017327283823856717, - "min": 0.020499208, - "max": 0.033622667 + "rss": 7192576, + "mean": 0.02151912460992908, + "stddev": 0.00039359916096075596, + "min": 0.02095425, + "max": 0.024327667 }, "dart": { "status": "ok", - "rss": 14548992, - "mean": 0.32955468740000005, - "stddev": 0.001223650636152885, - "min": 0.32698391600000004, - "max": 0.331166 + "rss": 14663680, + "mean": 0.33501409170000007, + "stddev": 0.008405730462685774, + "min": 0.328188083, + "max": 0.35789787500000003 }, "ocaml": { "status": "ok", - "rss": 2326528, - "mean": 0.028281900344827596, - "stddev": 0.0008786834824248314, - "min": 0.027441625, - "max": 0.034244292 + "rss": 2375680, + "mean": 0.029081769887850488, + "stddev": 0.001581199103748591, + "min": 0.027723875000000002, + "max": 0.035648042000000005 }, "haskell": { "status": "ok", - "rss": 11632640, - "mean": 0.039987035400000016, - "stddev": 0.0015718986917273865, - "min": 0.037153167, - "max": 0.042745167 + "rss": 11681792, + "mean": 0.040724149385714295, + "stddev": 0.0012051825657432395, + "min": 0.037733375, + "max": 0.042466792 }, - "rust-wasm": { + "osprey-wasm": { "status": "ok", "rss": 0, - "mean": 0.030032695870000018, - "stddev": 0.0013773490531421109, - "min": 0.028665208, - "max": 0.039225834 + "mean": 0.0404191793768116, + "stddev": 0.002723289705188686, + "min": 0.034653834, + "max": 0.0436985 }, + "rust-wasm": { + "status": "ok", + "rss": 0, + "mean": 0.029951737767676758, + "stddev": 0.00034344723335734265, + "min": 0.02925975, + "max": 0.031187708 + } + }, + "nestedloop": { "osprey": { "status": "ok", - "rss": 2093891584, - "mean": 0.7300477875000001, - "stddev": 0.010222214033245558, - "min": 0.713364042, - "max": 0.744938667 + "rss": 1572864, + "mean": 0.8705685292, + "stddev": 0.018192636548825872, + "min": 0.82779175, + "max": 0.8960859590000001 }, "osprey-arc": { "status": "ok", - "rss": 1540096, - "mean": 0.6854856625999999, - "stddev": 0.010211982367247975, - "min": 0.6710425830000001, - "max": 0.6957130420000001 + "rss": 1572864, + "mean": 0.5036864957999999, + "stddev": 0.004950494983310097, + "min": 0.4940955, + "max": 0.510229625 }, "osprey-gc": { "status": "ok", - "rss": 19464192, - "mean": 4.562711033499999, - "stddev": 0.06583094118124531, - "min": 4.448736833, - "max": 4.685815167 - } - }, - "nestedloop": { + "rss": 21151744, + "mean": 3.4625257622999994, + "stddev": 0.05650166542104579, + "min": 3.409761375, + "max": 3.573390833 + }, "rust": { "status": "ok", - "rss": 1589248, - "mean": 0.04615250769230768, - "stddev": 0.0008331177524516141, - "min": 0.04523075, - "max": 0.051802667000000004 + "rss": 1638400, + "mean": 0.046392036421875, + "stddev": 0.000194614526283047, + "min": 0.045848375000000004, + "max": 0.046835292 }, "c": { "status": "ok", - "rss": 1458176, - "mean": 0.04593367498461538, - "stddev": 0.0006864584262923693, - "min": 0.045166125, - "max": 0.049991542 + "rss": 1507328, + "mean": 0.04604509363076924, + "stddev": 0.0002416658171709289, + "min": 0.045446208, + "max": 0.046877166000000005 }, "csharp": { "status": "ok", - "rss": 7127040, - "mean": 0.04781424998387096, - "stddev": 0.00037808591663728887, - "min": 0.04696675, - "max": 0.049330125 + "rss": 7176192, + "mean": 0.048411964370967744, + "stddev": 0.0003057712330725844, + "min": 0.047970417, + "max": 0.049520917000000005 }, "dart": { "status": "ok", - "rss": 14581760, - "mean": 0.06139413193749999, - "stddev": 0.0015923017399531952, - "min": 0.059714667000000006, - "max": 0.070281834 + "rss": 14598144, + "mean": 0.06063248469387753, + "stddev": 0.0002810685758161171, + "min": 0.059912125000000004, + "max": 0.0615095 }, "ocaml": { "status": "ok", - "rss": 2310144, - "mean": 0.05821199837254903, - "stddev": 0.0005852348179840279, - "min": 0.057513458, - "max": 0.060023458 + "rss": 2342912, + "mean": 0.05848144856862744, + "stddev": 0.0001703133560630236, + "min": 0.058101833000000006, + "max": 0.058944500000000004 }, "haskell": { "status": "ok", - "rss": 11567104, - "mean": 0.06438383884782609, - "stddev": 0.0019353873038185404, - "min": 0.060757167, - "max": 0.07024812500000001 + "rss": 11616256, + "mean": 0.06523205968181818, + "stddev": 0.001626328072036853, + "min": 0.061459334000000004, + "max": 0.06757687500000001 }, - "rust-wasm": { + "osprey-wasm": { "status": "ok", "rss": 0, - "mean": 0.06247842640425531, - "stddev": 0.0008771476646762166, - "min": 0.060999875, - "max": 0.064719416 + "mean": 0.3816458207000001, + "stddev": 0.0033431267966799166, + "min": 0.37845812500000003, + "max": 0.389750417 }, + "rust-wasm": { + "status": "ok", + "rss": 0, + "mean": 0.06288545738297874, + "stddev": 0.00040113838645418494, + "min": 0.062268583, + "max": 0.064473458 + } + }, + "pascal": { "osprey": { "status": "ok", - "rss": 2513387520, - "mean": 0.8668739707, - "stddev": 0.010033923949978476, - "min": 0.8533714160000001, - "max": 0.884929666 + "rss": 1589248, + "mean": 1.6017045416000002, + "stddev": 0.02657780666501204, + "min": 1.558942542, + "max": 1.6454602500000002 }, "osprey-arc": { "status": "ok", - "rss": 1523712, - "mean": 0.8620227833000002, - "stddev": 0.011409290537939269, - "min": 0.8438698750000001, - "max": 0.8853095000000001 + "rss": 1589248, + "mean": 0.9367132873999999, + "stddev": 0.015439622477185826, + "min": 0.914458791, + "max": 0.9665296670000001 }, "osprey-gc": { "status": "ok", - "rss": 19496960, - "mean": 5.372185666799999, - "stddev": 0.09211998651374395, - "min": 5.216552042, - "max": 5.557882167 - } - }, - "pascal": { + "rss": 19513344, + "mean": 6.487253370900001, + "stddev": 0.5136110191140916, + "min": 5.869804709, + "max": 7.442191583 + }, "rust": { "status": "ok", - "rss": 1589248, - "mean": 0.027783211122641503, - "stddev": 0.0008361612485071879, - "min": 0.025691000000000002, - "max": 0.029878500000000002 + "rss": 1638400, + "mean": 0.02793113686238532, + "stddev": 0.000924974139562866, + "min": 0.02561625, + "max": 0.032024667 }, "c": { "status": "ok", - "rss": 1458176, - "mean": 0.028221163096153856, - "stddev": 0.0008988688041240006, - "min": 0.026292791000000003, - "max": 0.031024208 + "rss": 1507328, + "mean": 0.02816308256880736, + "stddev": 0.0009507916027086116, + "min": 0.025904584, + "max": 0.03032525 }, "csharp": { "status": "ok", - "rss": 7127040, - "mean": 0.03441754165168539, - "stddev": 0.0014440186941423864, - "min": 0.032214959, - "max": 0.042688875 + "rss": 7192576, + "mean": 0.03412298209302325, + "stddev": 0.0007390633165062962, + "min": 0.032829292, + "max": 0.036507458 }, "dart": { "status": "ok", "rss": 14548992, - "mean": 0.07060200895652174, - "stddev": 0.012173884804160352, - "min": 0.063950791, - "max": 0.130294333 + "mean": 0.06523930002222224, + "stddev": 0.0007131160681146469, + "min": 0.064509458, + "max": 0.069509375 }, "ocaml": { "status": "ok", - "rss": 2326528, - "mean": 0.05036319640677966, - "stddev": 0.004871912645357724, - "min": 0.044378584000000006, - "max": 0.067199083 + "rss": 2359296, + "mean": 0.04508688403125, + "stddev": 0.0006466955272116261, + "min": 0.044061625, + "max": 0.047143917 }, "haskell": { "status": "ok", - "rss": 11632640, - "mean": 0.06423500360869565, - "stddev": 0.0023414395233337633, - "min": 0.05492220900000001, - "max": 0.06745225 + "rss": 11681792, + "mean": 0.06495517245454546, + "stddev": 0.0026205266847213597, + "min": 0.054117167, + "max": 0.073449416 }, - "rust-wasm": { + "osprey-wasm": { "status": "ok", "rss": 0, - "mean": 0.04806589617460318, - "stddev": 0.0054867325584491596, - "min": 0.046021166, - "max": 0.080685167 + "mean": 0.9704858585, + "stddev": 0.007841018742537524, + "min": 0.960339041, + "max": 0.9843138750000001 }, + "rust-wasm": { + "status": "ok", + "rss": 0, + "mean": 0.04687504303125, + "stddev": 0.00037264659073324446, + "min": 0.046192583, + "max": 0.047776875 + } + }, + "powmod": { "osprey": { "status": "ok", - "rss": 2579070976, - "mean": 0.9630189458999998, - "stddev": 0.007148774683738517, - "min": 0.9501965840000001, - "max": 0.972110083 + "rss": 1572864, + "mean": 0.8838689166, + "stddev": 0.03405606009725339, + "min": 0.799863667, + "max": 0.914004958 }, "osprey-arc": { "status": "ok", - "rss": 1540096, - "mean": 0.9627446916, - "stddev": 0.008213396610624282, - "min": 0.947279791, - "max": 0.974808541 + "rss": 1605632, + "mean": 0.49852007080000005, + "stddev": 0.008414986914972625, + "min": 0.484675083, + "max": 0.51450375 }, "osprey-gc": { "status": "ok", - "rss": 19480576, - "mean": 5.5492239333, - "stddev": 0.07911438741774161, - "min": 5.410595542, - "max": 5.686219667 - } - }, - "powmod": { + "rss": 21659648, + "mean": 4.0187741666, + "stddev": 0.35297025468722837, + "min": 3.162964916, + "max": 4.282885 + }, "rust": { "status": "ok", - "rss": 1605632, - "mean": 0.02385397899999999, - "stddev": 0.0007207813896905064, - "min": 0.023232458, - "max": 0.029901916 + "rss": 1654784, + "mean": 0.027388738455357133, + "stddev": 0.002561400475798709, + "min": 0.025428875, + "max": 0.048440584 }, "c": { "status": "ok", - "rss": 1458176, - "mean": 0.02383265313492064, - "stddev": 0.0003161958272679855, - "min": 0.023335750000000002, - "max": 0.026078 + "rss": 1507328, + "mean": 0.02746493215740742, + "stddev": 0.0025949098436606243, + "min": 0.025318292000000003, + "max": 0.043577583 }, "csharp": { "status": "ok", - "rss": 7143424, - "mean": 0.03448549850000001, - "stddev": 0.0003400596927362209, - "min": 0.033720916000000004, - "max": 0.035523083000000004 + "rss": 7208960, + "mean": 0.04007976385897438, + "stddev": 0.0021943719305635174, + "min": 0.038081292, + "max": 0.052682042000000005 }, "dart": { "status": "ok", "rss": 14630912, - "mean": 0.05133039306666666, - "stddev": 0.00173732213051784, - "min": 0.04973475, - "max": 0.062088583 + "mean": 0.05878322717647061, + "stddev": 0.0013912402670083802, + "min": 0.057222708000000004, + "max": 0.066103166 }, "ocaml": { "status": "ok", - "rss": 2326528, - "mean": 0.061437497428571436, - "stddev": 0.0011554814301301542, - "min": 0.060642416000000005, - "max": 0.06902633300000001 + "rss": 2408448, + "mean": 0.07114654167499998, + "stddev": 0.0036232744768541405, + "min": 0.067888708, + "max": 0.08560358400000001 }, "haskell": { "status": "ok", - "rss": 11632640, - "mean": 0.06028439982692309, - "stddev": 0.0036673290038146972, - "min": 0.054440375000000006, - "max": 0.071232 + "rss": 11681792, + "mean": 0.06536304258695652, + "stddev": 0.0018276520664358246, + "min": 0.062160875000000004, + "max": 0.07296733300000001 }, - "rust-wasm": { + "osprey-wasm": { "status": "ok", "rss": 0, - "mean": 0.03457616568235294, - "stddev": 0.0018566667718908976, - "min": 0.033019125, - "max": 0.044864791 + "mean": 0.4077868499000001, + "stddev": 0.011953198259064298, + "min": 0.39738279200000004, + "max": 0.44049991600000005 }, + "rust-wasm": { + "status": "ok", + "rss": 0, + "mean": 0.03953326691891893, + "stddev": 0.0004430118409425512, + "min": 0.038543875000000005, + "max": 0.040602833000000005 + } + }, + "primes": { "osprey": { "status": "ok", - "rss": 1993375744, - "mean": 0.6870725541, - "stddev": 0.005549366181138516, - "min": 0.680312333, - "max": 0.6986373330000001 + "rss": 1589248, + "mean": 0.3163526752, + "stddev": 0.01298844391575426, + "min": 0.288164542, + "max": 0.329595625 }, "osprey-arc": { "status": "ok", - "rss": 1556480, - "mean": 0.6794077083, - "stddev": 0.00833965896678391, - "min": 0.66477925, - "max": 0.6925119160000001 + "rss": 1589248, + "mean": 0.17164780641176472, + "stddev": 0.0027966530082497096, + "min": 0.16646375000000002, + "max": 0.17604529100000002 }, "osprey-gc": { "status": "ok", - "rss": 19480576, - "mean": 4.3323569084, - "stddev": 0.054545445823862435, - "min": 4.26208475, - "max": 4.417397084 - } - }, - "primes": { + "rss": 20578304, + "mean": 1.2567980418, + "stddev": 0.18758316390566937, + "min": 1.081088917, + "max": 1.501733625 + }, "rust": { "status": "ok", - "rss": 1589248, - "mean": 0.006858740650862062, - "stddev": 0.0004869576800498768, - "min": 0.006439834, - "max": 0.014982459000000002 + "rss": 1638400, + "mean": 0.007063593375286041, + "stddev": 0.0006971177691787049, + "min": 0.006606459, + "max": 0.014957709000000001 }, "c": { "status": "ok", - "rss": 1441792, - "mean": 0.006616631962555068, - "stddev": 0.00046419280702970824, - "min": 0.006226375, - "max": 0.015553583000000001 + "rss": 1507328, + "mean": 0.0071137596083743915, + "stddev": 0.0009213600659026741, + "min": 0.006427166000000001, + "max": 0.015955792 }, "csharp": { "status": "ok", - "rss": 7143424, - "mean": 0.008806346412429384, - "stddev": 0.0007743658020047052, - "min": 0.007873584000000001, - "max": 0.012502708000000001 + "rss": 7208960, + "mean": 0.010741415864468867, + "stddev": 0.0009915879433960557, + "min": 0.009115584000000001, + "max": 0.019529917 }, "dart": { "status": "ok", - "rss": 14581760, - "mean": 0.04493854613636365, - "stddev": 0.0009853338668188623, - "min": 0.043465208000000005, - "max": 0.050328500000000005 + "rss": 14630912, + "mean": 0.0525505778888889, + "stddev": 0.0026278437657826586, + "min": 0.045885083, + "max": 0.06313895900000001 }, "ocaml": { "status": "ok", - "rss": 2310144, - "mean": 0.00912500850427351, - "stddev": 0.0009359027374746489, - "min": 0.008186, - "max": 0.013190750000000001 + "rss": 2359296, + "mean": 0.010040104651408453, + "stddev": 0.0017698016681841398, + "min": 0.00918125, + "max": 0.037185333 }, "haskell": { "status": "ok", - "rss": 11616256, - "mean": 0.017901848300653587, - "stddev": 0.0016329240369125052, - "min": 0.014320083, - "max": 0.02233525 + "rss": 11681792, + "mean": 0.01866693177127659, + "stddev": 0.0043147849121591125, + "min": 0.015194375000000001, + "max": 0.043029917 }, - "rust-wasm": { + "osprey-wasm": { "status": "ok", "rss": 0, - "mean": 0.017280983664739895, - "stddev": 0.0005869880946908597, - "min": 0.016139792, - "max": 0.021417959 + "mean": 0.1444382102857143, + "stddev": 0.005628192167287868, + "min": 0.138395458, + "max": 0.162523584 }, + "rust-wasm": { + "status": "ok", + "rss": 0, + "mean": 0.021014244541095895, + "stddev": 0.0012618442241865656, + "min": 0.019611916, + "max": 0.030586250000000002 + } + }, + "tak": { "osprey": { "status": "ok", - "rss": 687669248, - "mean": 0.23849453125000009, - "stddev": 0.005513239178455607, - "min": 0.233807959, - "max": 0.253079333 + "rss": 1572864, + "mean": 0.5980348707, + "stddev": 0.03091600843818924, + "min": 0.5506717090000001, + "max": 0.649924625 }, "osprey-arc": { "status": "ok", - "rss": 1556480, - "mean": 0.2297935576153846, - "stddev": 0.003795437223385899, - "min": 0.22396691600000002, - "max": 0.23786979200000002 + "rss": 1605632, + "mean": 0.36374118730000005, + "stddev": 0.010699309167070249, + "min": 0.348362875, + "max": 0.387440125 }, "osprey-gc": { "status": "ok", - "rss": 19447808, - "mean": 1.4728300791, - "stddev": 0.01588407109041241, - "min": 1.455810375, - "max": 1.505744 - } - }, - "tak": { + "rss": 21528576, + "mean": 2.6732468125, + "stddev": 0.04659590489632291, + "min": 2.602303542, + "max": 2.75789175 + }, "rust": { "status": "ok", - "rss": 1589248, - "mean": 0.03315593641573033, - "stddev": 0.000726064248935122, - "min": 0.032212375, - "max": 0.036054041 + "rss": 1638400, + "mean": 0.03745146140243903, + "stddev": 0.0013028373729032257, + "min": 0.035566625000000004, + "max": 0.044387583 }, "c": { "status": "ok", - "rss": 1441792, - "mean": 0.03304168240000001, - "stddev": 0.00045241928619759976, - "min": 0.032062708, - "max": 0.034718 + "rss": 1490944, + "mean": 0.037343646582278504, + "stddev": 0.0004604617251843627, + "min": 0.036643708000000004, + "max": 0.039096166 }, "csharp": { "status": "ok", - "rss": 7143424, - "mean": 0.03565940535294119, - "stddev": 0.0018913848143293664, - "min": 0.034323084000000004, - "max": 0.047146458 + "rss": 7208960, + "mean": 0.04051666495945945, + "stddev": 0.002467559229926767, + "min": 0.039002917000000005, + "max": 0.05935225 }, "dart": { "status": "ok", - "rss": 14532608, - "mean": 0.0826068113611111, - "stddev": 0.0007316112089590896, - "min": 0.08171625, - "max": 0.084680375 + "rss": 14598144, + "mean": 0.09331734112500001, + "stddev": 0.0027316746966978113, + "min": 0.08800816700000001, + "max": 0.103786875 }, "ocaml": { "status": "ok", - "rss": 2326528, - "mean": 0.04510011532307694, - "stddev": 0.0006985645310739489, - "min": 0.043992042, - "max": 0.048574459 + "rss": 2392064, + "mean": 0.05120066454237288, + "stddev": 0.001444101192154177, + "min": 0.049749333, + "max": 0.061165708000000006 }, "haskell": { "status": "ok", - "rss": 11632640, - "mean": 0.06847435663414636, - "stddev": 0.004540421695230339, - "min": 0.059483791, - "max": 0.075231584 + "rss": 11698176, + "mean": 0.07503934534210525, + "stddev": 0.004418385553868426, + "min": 0.06576037500000001, + "max": 0.07998358300000001 }, - "rust-wasm": { + "osprey-wasm": { "status": "ok", "rss": 0, - "mean": 0.0992570707878788, - "stddev": 0.0325106497953417, - "min": 0.08995383400000001, - "max": 0.24615270800000003 + "mean": 0.4805015333, + "stddev": 0.0066731378526374025, + "min": 0.470438375, + "max": 0.49254108300000005 }, + "rust-wasm": { + "status": "ok", + "rss": 0, + "mean": 0.09200139181250001, + "stddev": 0.001017740810014639, + "min": 0.090094292, + "max": 0.094946917 + } + }, + "textstats": { "osprey": { "status": "ok", - "rss": 1218543616, - "mean": 0.47141332069999997, - "stddev": 0.004846752931971514, - "min": 0.46590966600000006, - "max": 0.48066745800000005 + "rss": 1589248, + "mean": 0.023291517108527136, + "stddev": 0.0005574372895929533, + "min": 0.021812041, + "max": 0.024825458 }, "osprey-arc": { "status": "ok", - "rss": 1523712, - "mean": 0.46883670009999995, - "stddev": 0.006699399354727906, - "min": 0.457516792, - "max": 0.47952225000000004 + "rss": 1638400, + "mean": 0.016009942196721322, + "stddev": 0.0002235780671157969, + "min": 0.015244459, + "max": 0.016711 }, "osprey-gc": { "status": "ok", - "rss": 19759104, - "mean": 2.5668085458, - "stddev": 0.028892475084118834, - "min": 2.514168875, - "max": 2.601385625 - } - }, - "textstats": { + "rss": 19529728, + "mean": 0.07505139492499999, + "stddev": 0.002305663647159922, + "min": 0.071298708, + "max": 0.08289508400000001 + }, "rust": { "status": "ok", - "rss": 1638400, - "mean": 0.002038718148710169, - "stddev": 0.00020278796089876684, - "min": 0.001778833, - "max": 0.004821541 + "rss": 1687552, + "mean": 0.002022091545517244, + "stddev": 9.951903182056918e-05, + "min": 0.0018505000000000001, + "max": 0.0032279580000000004 }, "c": { "status": "ok", - "rss": 1458176, - "mean": 0.0021485928374040462, - "stddev": 0.00026120975099472115, - "min": 0.001876875, - "max": 0.009747542000000001 + "rss": 1507328, + "mean": 0.002175474886462879, + "stddev": 0.00015412805545224058, + "min": 0.001979167, + "max": 0.005125459000000001 }, "csharp": { "status": "ok", - "rss": 7110656, - "mean": 0.003650256035308945, - "stddev": 0.000325117441146096, - "min": 0.0030687920000000003, - "max": 0.005873708 + "rss": 7159808, + "mean": 0.003753834999999996, + "stddev": 0.00019152823746652135, + "min": 0.0033761670000000002, + "max": 0.0044985830000000004 }, "dart": { "status": "ok", - "rss": 14663680, - "mean": 0.01180029183196721, - "stddev": 0.0007433458631067606, - "min": 0.01033325, - "max": 0.017608916000000002 + "rss": 14680064, + "mean": 0.01138889645864661, + "stddev": 0.0004481804057695586, + "min": 0.010584458000000001, + "max": 0.014636292 }, "ocaml": { "status": "ok", - "rss": 2392064, - "mean": 0.003965607458666661, - "stddev": 0.00018976701046523038, - "min": 0.0036033750000000002, - "max": 0.0057245410000000005 + "rss": 2424832, + "mean": 0.0040443972076502745, + "stddev": 0.00039978387797189795, + "min": 0.003721666, + "max": 0.0097745 }, "haskell": { "status": "ok", - "rss": 11911168, - "mean": 0.01781794001630435, - "stddev": 0.001996248352272995, - "min": 0.014241833, - "max": 0.031193042 + "rss": 11960320, + "mean": 0.016683873355555556, + "stddev": 0.001496574159417358, + "min": 0.014044875, + "max": 0.030265875 }, - "rust-wasm": { + "osprey-wasm": { "status": "ok", "rss": 0, - "mean": 0.012800005684210528, - "stddev": 0.00055987271414742, - "min": 0.011680416, - "max": 0.015609250000000002 + "mean": 0.025163726890756296, + "stddev": 0.0026947560655463626, + "min": 0.023543167, + "max": 0.051244375 }, + "rust-wasm": { + "status": "ok", + "rss": 0, + "mean": 0.014921016449152549, + "stddev": 0.006218366170646818, + "min": 0.012566417000000002, + "max": 0.088071625 + } + }, + "wordfreq": { "osprey": { "status": "ok", - "rss": 59424768, - "mean": 0.0238211570873016, - "stddev": 0.0007541397329070309, - "min": 0.022458459, - "max": 0.0270735 + "rss": 61947904, + "mean": 0.03745674675999999, + "stddev": 0.0006750681300732871, + "min": 0.036360916, + "max": 0.039533333000000004 }, "osprey-arc": { "status": "ok", - "rss": 1605632, - "mean": 0.024795744512396693, - "stddev": 0.0005842535274048718, - "min": 0.023553125, - "max": 0.026635958 + "rss": 1720320, + "mean": 0.04028635358333334, + "stddev": 0.0006124224695742778, + "min": 0.038935209000000005, + "max": 0.04243 }, "osprey-gc": { "status": "ok", - "rss": 15548416, - "mean": 0.12317802433333336, - "stddev": 0.0020555486270009814, - "min": 0.120131291, - "max": 0.127006167 - } - }, - "wordfreq": { + "rss": 18890752, + "mean": 0.14166789085714285, + "stddev": 0.004795305469611225, + "min": 0.134459459, + "max": 0.15001387500000002 + }, "rust": { "status": "ok", - "rss": 1654784, - "mean": 0.004491582085014406, - "stddev": 0.0003528588947357426, - "min": 0.004125167, - "max": 0.010912167 + "rss": 1703936, + "mean": 0.00446571044709389, + "stddev": 0.00011080374462978175, + "min": 0.004239584, + "max": 0.0049778750000000005 }, "c": { "status": "ok", - "rss": 1441792, - "mean": 0.0014984965388571468, - "stddev": 0.00017509126005132804, - "min": 0.001265375, - "max": 0.003776708 + "rss": 1490944, + "mean": 0.0014656763577755947, + "stddev": 0.00011792661509350858, + "min": 0.0013238750000000002, + "max": 0.0045334170000000005 }, "csharp": { "status": "ok", - "rss": 7094272, - "mean": 0.0032858749850402727, - "stddev": 0.0006074346340844559, - "min": 0.002755125, - "max": 0.018445125 + "rss": 7143424, + "mean": 0.003340165967032972, + "stddev": 0.00018840195715992108, + "min": 0.0030474160000000003, + "max": 0.00437975 }, "dart": { "status": "ok", "rss": 14663680, - "mean": 0.011533439093283585, - "stddev": 0.0008564840871921605, - "min": 0.009810209, - "max": 0.015979875 + "mean": 0.010558956003745316, + "stddev": 0.00028843210793335044, + "min": 0.009899583, + "max": 0.011505083000000001 }, "ocaml": { "status": "ok", - "rss": 2408448, - "mean": 0.002597158961668544, - "stddev": 0.00041606917024890794, - "min": 0.00219, - "max": 0.007880125 + "rss": 2457600, + "mean": 0.00248328193859649, + "stddev": 0.0002040057932570796, + "min": 0.002235209, + "max": 0.005594208000000001 }, "haskell": { "status": "ok", - "rss": 11862016, - "mean": 0.01775372352486188, - "stddev": 0.0017357853521831922, - "min": 0.01428275, - "max": 0.023103708 + "rss": 11911168, + "mean": 0.016398375948571443, + "stddev": 0.0006323862058135307, + "min": 0.014310542, + "max": 0.017725292 }, - "rust-wasm": { + "osprey-wasm": { "status": "ok", "rss": 0, - "mean": 0.01565222973298431, - "stddev": 0.0005195457386605876, - "min": 0.014402708, - "max": 0.017833917 - }, - "osprey": { - "status": "ok", - "rss": 106905600, - "mean": 0.040911095119402975, - "stddev": 0.0018370908419779348, - "min": 0.038914959, - "max": 0.048076375000000005 - }, - "osprey-arc": { - "status": "ok", - "rss": 1654784, - "mean": 0.04779211825806452, - "stddev": 0.0010808614944953646, - "min": 0.045554416, - "max": 0.051259375 + "mean": 0.04565770137878788, + "stddev": 0.0006245844973793937, + "min": 0.044278084, + "max": 0.047725500000000004 }, - "osprey-gc": { + "rust-wasm": { "status": "ok", - "rss": 18972672, - "mean": 0.18743808350000005, - "stddev": 0.006892849993496759, - "min": 0.179939292, - "max": 0.19935775 + "rss": 0, + "mean": 0.015666853932291665, + "stddev": 0.00027623987768515346, + "min": 0.014974875, + "max": 0.016600833000000002 } } } diff --git a/crates/osprey-ast/src/canonical.rs b/crates/osprey-ast/src/canonical.rs new file mode 100644 index 00000000..b3245334 --- /dev/null +++ b/crates/osprey-ast/src/canonical.rs @@ -0,0 +1,165 @@ +//! Position-blind program rendering. +//! +//! A [`Position`](crate::Position) records *where* a node was written, never +//! what it means, yet it participates in `Program`'s derived `PartialEq`. Two +//! callers need to ask whether two ASTs say the same thing while allowing them +//! to sit at different coordinates: +//! +//! * the formatter's meaning-preservation guard, whose entire purpose is to +//! move nodes — comparing positions there rejects exactly the reindentation +//! the formatter exists to perform; +//! * the cross-flavor equivalence tests, where the same program written in the +//! brace and layout surfaces necessarily lands on different lines. +//! +//! Both get [`without_positions`] rather than a hand-written traversal, which +//! would have to be extended every time a node gains a position and would fail +//! silently — as a stale comparison — when it was not. + +use crate::Program; + +/// Render `program` with every source coordinate removed, so two renderings +/// compare equal exactly when the programs mean the same thing. +/// +/// The pretty-`Debug` form puts each field on its own line and escapes string +/// contents onto a single line, so the shapes below are unambiguous: a string +/// literal always shares its line with its own quotes and can never be mistaken +/// for one of them. +/// +/// Both the *coordinates* and the *presence* of a position are erased — +/// `position: None` and `position: Some(Position { … })` render alike — because +/// whether a frontend happened to record a span is metadata about parsing, not +/// about meaning. The one shape left alone is a bare `None` in a tuple variant, +/// which is indistinguishable from any other absent field; a divergence there +/// is reported rather than assumed benign. +#[must_use] +pub fn without_positions(program: &Program) -> String { + let dump = format!("{program:#?}"); + let lines: Vec<&str> = dump.lines().collect(); + let mut out = Vec::with_capacity(lines.len()); + let mut index = 0; + while let Some(line) = lines.get(index) { + if let Some(next) = position_field(&lines, index) { + out.push(format!("{}position: ", " ".repeat(indent_of(line)))); + index = next; + } else { + out.push((*line).to_owned()); + index = index.saturating_add(1); + } + } + out.join("\n") +} + +/// If the line at `index` opens a position field, the index just past it. +/// +/// Three spellings reach here: the absent named field, the present named field, +/// and the present *tuple* field, whose `Some(` carries no field name and so is +/// recognised by the `Position {` on the following line. +fn position_field(lines: &[&str], index: usize) -> Option { + let trimmed = lines.get(index)?.trim_start(); + if trimmed == "position: None," { + return Some(index.saturating_add(1)); + } + let opens = trimmed == "position: Some(" || trimmed == "Some("; + let holds_position = lines + .get(index.saturating_add(1)) + .is_some_and(|next| next.trim_start() == "Position {"); + (opens && holds_position).then(|| closer(lines, index))? +} + +/// The index just past the `),` closing the `Some(` at `index`: the pretty form +/// indents every nested line further, so the first close back at that line's own +/// column is the matching one. +fn closer(lines: &[&str], index: usize) -> Option { + let indent = indent_of(lines.get(index)?); + lines + .iter() + .enumerate() + .skip(index.saturating_add(1)) + .find(|(_, line)| line.trim_start() == ")," && indent_of(line) == indent) + .map(|(at, _)| at.saturating_add(1)) +} + +/// Width of a line's leading whitespace. +fn indent_of(line: &str) -> usize { + line.len().saturating_sub(line.trim_start().len()) +} + +#[cfg(test)] +mod tests { + use super::without_positions; + use crate::{Expr, Position, Program, Stmt}; + + fn let_at(value: &str, position: Option) -> Stmt { + Stmt::Let { + name: "a".to_owned(), + mutable: false, + ty: None, + value: Expr::Str(value.to_owned()), + doc: None, + position, + } + } + + #[test] + fn the_same_program_at_different_coordinates_renders_identically() { + let here = Program { + statements: vec![let_at("x", Some(Position { line: 1, column: 0 }))], + }; + let there = Program { + statements: vec![let_at( + "x", + Some(Position { + line: 90, + column: 12, + }), + )], + }; + assert_ne!(here, there, "the derived equality does compare positions"); + assert_eq!(without_positions(&here), without_positions(&there)); + } + + #[test] + fn a_difference_that_is_not_a_coordinate_survives() { + let one = Program { + statements: vec![let_at("x", None)], + }; + let other = Program { + statements: vec![let_at("y", None)], + }; + assert_ne!(without_positions(&one), without_positions(&other)); + } + + /// The hazard the line-oriented filter has to survive: a program whose own + /// string data is spelled like a coordinate. `{:#?}` keeps the literal on + /// one line with its quotes, so it is never mistaken for one. + #[test] + fn a_string_literal_spelled_like_a_coordinate_is_not_stripped() { + let literal = "line: 42,\ncolumn: 7,"; + let program = Program { + statements: vec![let_at(literal, None)], + }; + let other = Program { + statements: vec![let_at("column: 7,\nline: 42,", None)], + }; + assert!(without_positions(&program).contains("line: 42")); + assert_ne!(without_positions(&program), without_positions(&other)); + } + + /// A frontend that records a span and one that does not must still compare + /// equal: whether a position was captured is a fact about parsing. + #[test] + fn a_recorded_position_and_an_absent_one_render_alike() { + let recorded = Program { + statements: vec![let_at("x", Some(Position { line: 3, column: 1 }))], + }; + let absent = Program { + statements: vec![let_at("x", None)], + }; + assert_eq!(without_positions(&recorded), without_positions(&absent)); + assert!( + !without_positions(&recorded).contains("Position"), + "{}", + without_positions(&recorded) + ); + } +} diff --git a/crates/osprey-ast/src/lib.rs b/crates/osprey-ast/src/lib.rs index 481cff70..2b7ca5d9 100644 --- a/crates/osprey-ast/src/lib.rs +++ b/crates/osprey-ast/src/lib.rs @@ -5,6 +5,7 @@ //! enums means the type checker and codegen get compiler-enforced totality for //! free: adding a variant breaks every consumer until it handles the new form. +pub mod canonical; mod doc; mod generics; mod lower_static; diff --git a/crates/osprey-cli/tests/cross_flavor_equiv.rs b/crates/osprey-cli/tests/cross_flavor_equiv.rs index 779e3518..f85edc45 100644 --- a/crates/osprey-cli/tests/cross_flavor_equiv.rs +++ b/crates/osprey-cli/tests/cross_flavor_equiv.rs @@ -24,25 +24,11 @@ fn canonical(src: &str, flavor: Flavor) -> String { "unexpected {flavor} syntax errors: {:?}", parsed.errors ); - scrub_positions(&format!("{:?}", parsed.program)) + osprey_ast::canonical::without_positions(&parsed.program) } /// Drop every `Position { line: N, column: M }` from a debug string. `Position` /// has no nested braces, so the next `}` always closes it. -fn scrub_positions(debug: &str) -> String { - let mut out = String::with_capacity(debug.len()); - let mut rest = debug; - while let Some(idx) = rest.find("Position {") { - out.push_str(&rest[..idx]); - rest = &rest[idx..]; - match rest.find('}') { - Some(close) => rest = &rest[close + 1..], - None => break, - } - } - out.push_str(rest); - out -} #[test] fn doc_comments_lower_identically_across_flavors() { diff --git a/crates/osprey-fmt/src/brace.rs b/crates/osprey-fmt/src/brace.rs index 50453493..2dd0a029 100644 --- a/crates/osprey-fmt/src/brace.rs +++ b/crates/osprey-fmt/src/brace.rs @@ -6,12 +6,12 @@ //! that *begins* by closing brackets dedents to match its opener. Comments adopt //! the depth of the surrounding block. -use crate::scan::{scan_line, Line}; +use crate::scan::{scan_source, Line}; use crate::{finalize, indent_to}; /// Reformat Default-flavor `src`, returning the canonical, reindented text. pub(crate) fn format(src: &str) -> String { - let lines: Vec = src.split('\n').map(scan_line).collect(); + let lines: Vec = scan_source(src); let mut depth = 0i32; let mut out: Vec = Vec::with_capacity(lines.len()); for line in &lines { @@ -58,6 +58,17 @@ mod tests { assert_eq!(format(&once), once); } + /// A literal written across several lines carries its own newlines and + /// interior spacing as *data*. Reindenting them rewrote what the program + /// printed — caught only because the reparse guard is loud. + #[test] + fn a_multi_line_string_literal_is_not_reindented() { + let src = "fn f() = {\nprint(\"one\n two two\nthree\")\nx\n}\n"; + let want = "fn f() = {\n print(\"one\n two two\nthree\")\n x\n}\n"; + assert_eq!(format(src), want); + assert_eq!(format(&format(src)), format(src), "not idempotent"); + } + #[test] fn brackets_inside_strings_do_not_shift_indentation() { let src = "fn f() = {\nprint(\"}{}{\")\nx\n}\n"; diff --git a/crates/osprey-fmt/src/layout.rs b/crates/osprey-fmt/src/layout.rs index 06bba6da..499dfc5c 100644 --- a/crates/osprey-fmt/src/layout.rs +++ b/crates/osprey-fmt/src/layout.rs @@ -8,12 +8,12 @@ //! siblings. Blank and comment lines are layout-transparent; a standalone //! comment takes the depth of the code it precedes. -use crate::scan::{scan_line, Line}; +use crate::scan::{scan_source, Line}; use crate::{finalize, indent_to}; /// Reformat ML-flavor `src`, re-gridding its layout to a four-space step. pub(crate) fn format(src: &str) -> String { - let lines: Vec = src.split('\n').map(scan_line).collect(); + let lines: Vec = scan_source(src); let depths = code_depths(&lines); let out = render(&lines, &depths); finalize(&out) diff --git a/crates/osprey-fmt/src/lib.rs b/crates/osprey-fmt/src/lib.rs index cffc6f6e..dd7c5c05 100644 --- a/crates/osprey-fmt/src/lib.rs +++ b/crates/osprey-fmt/src/lib.rs @@ -8,10 +8,11 @@ //! //! * **Meaning-preserving.** After reformatting, the candidate text is reparsed //! and its AST is compared to the original's. If they differ in any way (or the -//! candidate fails to parse), the original source is returned untouched. ML -//! input also has one constrained recovery for an accidentally dedented suffix: -//! it is accepted only when indenting from a reported error restores a complete -//! parse. +//! candidate fails to parse), the file is left unchanged and the rejection is +//! **reported** — it is the formatter's own defect, so it is never swallowed +//! into a result indistinguishable from "already formatted". ML input also has +//! one constrained recovery for an accidentally dedented suffix: it is accepted +//! only when indenting from a reported error restores a complete parse. //! * **Idempotent.** Formatting already-formatted text is a no-op. //! //! The same function backs both the `osprey fmt` CLI command and the language @@ -32,7 +33,9 @@ const INDENT_WIDTH: usize = 4; /// /// # Errors /// Returns the source's syntax errors (as `line:col: message` strings) when the -/// input does not parse, except for a recoverable dedented ML suffix. +/// input does not parse, except for a recoverable dedented ML suffix; or +/// [`DECLINED`] when the formatter's own output fails the meaning-preservation +/// guard in [`accept`]. pub fn format_source(src: &str, flavor: Flavor) -> Result> { let mut source = src.to_owned(); let mut parsed = osprey_syntax::parse_program_with_flavor(&source, flavor); @@ -49,11 +52,7 @@ pub fn format_source(src: &str, flavor: Flavor) -> Result> { Flavor::Default => brace::format(&source), Flavor::Ml => layout::format(&source), }; - if preserves_meaning(&parsed.program, &candidate, flavor) { - Ok(candidate) - } else { - Ok(source) - } + accept(&parsed.program, candidate, flavor) } /// Format `src` using the flavor resolved from `path` (its extension and any @@ -69,11 +68,46 @@ pub fn format_for_path(path: &str, src: &str) -> Result> { } } -/// Whether `candidate` reparses to exactly the same program as the original — -/// the guard that makes formatting meaning-preserving. -fn preserves_meaning(original: &osprey_ast::Program, candidate: &str, flavor: Flavor) -> bool { - let reparsed = osprey_syntax::parse_program_with_flavor(candidate, flavor); - reparsed.errors.is_empty() && &reparsed.program == original +/// Reported when the reparse guard rejects the formatter's own output. +/// +/// The wording says whose fault it is, because it is never the author's: the +/// input parsed cleanly a moment earlier. +pub const DECLINED: &str = + "formatter declined: its own output does not reparse to the same program (formatter defect); \ + the file is left unchanged"; + +/// The guard that makes formatting meaning-preserving: `candidate` is returned +/// only when it reparses to exactly the same program as the original. +/// +/// A rejection is **reported**, not swallowed. Returning the input verbatim +/// instead — as this did until plan 0019 closed it — is indistinguishable from +/// "this file was already formatted", so a formatter that had stopped +/// formatting a whole class of file would sail through the corpus audit and +/// through `osprey fmt --check` alike. +/// +/// # Errors +/// Returns [`DECLINED`], followed by the candidate's own syntax errors when it +/// no longer parses at all. +fn accept( + original: &osprey_ast::Program, + candidate: String, + flavor: Flavor, +) -> Result> { + let reparsed = osprey_syntax::parse_program_with_flavor(&candidate, flavor); + if !reparsed.errors.is_empty() { + return Err(std::iter::once(DECLINED.to_owned()) + .chain(reparsed.errors.iter().map(error_line)) + .collect()); + } + // Compared without source coordinates: moving a node to a new line is the + // whole point of formatting, so a position difference is the one difference + // that must not count ([`osprey_ast::canonical`]). + if osprey_ast::canonical::without_positions(&reparsed.program) + == osprey_ast::canonical::without_positions(original) + { + return Ok(candidate); + } + Err(vec![DECLINED.to_owned()]) } /// Render a syntax error as `line:col: message`. @@ -180,6 +214,43 @@ mod tests { assert!(result.is_err(), "{result:?}"); } + /// A candidate that reparses cleanly but to a *different* program is the + /// dangerous shape: nothing downstream would notice. Reached directly, + /// because the real formatter is not supposed to be able to produce it. + #[test] + fn a_candidate_that_changes_meaning_is_reported_not_returned_as_the_input() { + let original = osprey_syntax::parse_program("let a = 1\n").program; + let result = accept(&original, "let a = 2\n".to_owned(), Flavor::Default); + assert_eq!(result, Err(vec![DECLINED.to_owned()])); + } + + /// A candidate that no longer parses carries its own errors after the + /// verdict, so the formatter defect can be located. + #[test] + fn an_unparseable_candidate_reports_the_verdict_and_its_errors() { + let original = osprey_syntax::parse_program("let a = 1\n").program; + let result = accept(&original, "let a = {\n".to_owned(), Flavor::Default); + match result { + Err(errors) => { + assert_eq!(errors.first().map(String::as_str), Some(DECLINED)); + assert!(errors.len() > 1, "no candidate errors: {errors:?}"); + } + Ok(text) => assert_eq!(text, DECLINED, "declined candidate accepted"), + } + } + + /// The accepting direction, so the two tests above cannot pass by the guard + /// having been wired to reject everything. + #[test] + fn an_equivalent_candidate_is_returned_verbatim() { + let original = osprey_syntax::parse_program("let a = 1\n").program; + let candidate = "let a = 1\n".to_owned(); + assert_eq!( + accept(&original, candidate.clone(), Flavor::Default), + Ok(candidate) + ); + } + #[test] fn path_resolves_flavor_from_extension() { assert!(format_for_path("a.ospml", "main () =\n print 1\n").is_ok()); diff --git a/crates/osprey-fmt/src/scan.rs b/crates/osprey-fmt/src/scan.rs index 1b05570f..c01db266 100644 --- a/crates/osprey-fmt/src/scan.rs +++ b/crates/osprey-fmt/src/scan.rs @@ -22,6 +22,9 @@ pub(crate) struct Line { /// How many closing brackets the content opens with (a line that *starts* by /// closing a block dedents itself by this many levels). pub leading_closers: i32, + /// Whether the line ends inside an unterminated string literal, so the + /// following physical line is part of that literal's *value*. + pub open_string: bool, } impl Line { @@ -43,7 +46,7 @@ pub(crate) fn scan_line(raw: &str) -> Line { .iter() .take_while(|c| **c == ' ' || **c == '\t') .count(); - let (content, open_delta) = normalize(chars.get(leading_ws..).unwrap_or_default()); + let (content, open_delta, open_string) = normalize(chars.get(leading_ws..).unwrap_or_default()); let leading_closers = content .chars() .take_while(|c| matches!(c, '}' | ')' | ']')) @@ -53,22 +56,56 @@ pub(crate) fn scan_line(raw: &str) -> Line { content, open_delta, leading_closers: i32::try_from(leading_closers).unwrap_or(0), + open_string, } } +/// Scan a whole source into logical lines, **merging** the physical lines a +/// string literal spans into one. +/// +/// A newline written inside `"…"` is part of a value, not of the layout, so it +/// must survive reformatting byte for byte. Scanning line by line cannot see +/// that: the continuation lines look like code and get reindented and +/// whitespace-collapsed, silently rewriting what the program prints. Merging +/// makes the reindenter blind to the literal — the whole thing moves as one +/// unit and only the line that opens it is indented. +pub(crate) fn scan_source(src: &str) -> Vec { + let mut lines = Vec::new(); + let mut open: Option = None; + for raw in src.split('\n') { + let merged = match open.take() { + Some(previous) => previous + "\n" + raw, + None => raw.to_owned(), + }; + let line = scan_line(&merged); + if line.open_string { + open = Some(merged); + } else { + lines.push(line); + } + } + // Unterminated at end of input: the source does not parse, so the guard in + // `format_source` has already rejected it. Emit it rather than drop it. + lines.extend(open.as_deref().map(scan_line)); + lines +} + /// Normalise the post-indent part of a line: collapse interior whitespace, /// trim the end, copy strings/comments verbatim, and tally bracket nesting. -fn normalize(chars: &[char]) -> (String, i32) { +fn normalize(chars: &[char]) -> (String, i32, bool) { let mut out = String::with_capacity(chars.len()); let mut delta = 0i32; let mut i = 0; + let mut open_string = false; while let Some(&c) = chars.get(i) { if c == '/' && chars.get(i + 1) == Some(&'/') { out.extend(chars.get(i..).unwrap_or_default()); break; } if c == '"' { - i = copy_string(chars, i, &mut out); + let (next, terminated) = copy_string(chars, i, &mut out); + i = next; + open_string = !terminated; } else if c == ' ' || c == '\t' { out.push(' '); i += chars @@ -82,7 +119,14 @@ fn normalize(chars: &[char]) -> (String, i32) { i += 1; } } - (out.trim_end().to_string(), delta) + // A line that ends inside a literal keeps its trailing spaces: they are + // part of the value, not layout. + let content = if open_string { + out + } else { + out.trim_end().to_string() + }; + (content, delta, open_string) } /// The nesting contribution of a single character: `+1` to open a block-forming @@ -97,9 +141,12 @@ fn bracket_delta(c: char) -> i32 { } /// Copy a string literal verbatim starting at the opening quote `chars[start]`, -/// returning the index just past the closing quote (or end of line if -/// unterminated). Escapes are preserved and `${…}` interpolation is delegated. -fn copy_string(chars: &[char], start: usize, out: &mut String) -> usize { +/// returning the index just past the closing quote and whether that quote was +/// found. Escapes are preserved and `${…}` interpolation is delegated. +/// +/// An unterminated literal is not an error here: the input may simply be one +/// physical line of a literal that spans several ([`scan_source`]). +fn copy_string(chars: &[char], start: usize, out: &mut String) -> (usize, bool) { out.push('"'); let mut i = start + 1; while let Some(&c) = chars.get(i) { @@ -113,31 +160,43 @@ fn copy_string(chars: &[char], start: usize, out: &mut String) -> usize { } '"' => { out.push('"'); - return i + 1; + return (i + 1, true); + } + '$' if chars.get(i + 1) == Some(&'{') => { + let (next, closed) = copy_interpolation(chars, i, out); + i = next; + if !closed { + return (i, false); + } } - '$' if chars.get(i + 1) == Some(&'{') => i = copy_interpolation(chars, i, out), other => { out.push(other); i += 1; } } } - i + (i, false) } /// Copy a `${…}` interpolation verbatim starting at the `$` (`chars[start]`), /// honouring nested braces and nested strings so the matching `}` is found even -/// inside an embedded string. Returns the index just past that `}`. -fn copy_interpolation(chars: &[char], start: usize, out: &mut String) -> usize { +/// inside an embedded string. Returns the index just past that `}` and whether +/// it was found — an interpolation left open at end of input means the +/// enclosing literal is still open too. +fn copy_interpolation(chars: &[char], start: usize, out: &mut String) -> (usize, bool) { out.push('$'); out.push('{'); let mut i = start + 2; let mut depth = 1i32; while depth > 0 { match chars.get(i) { - None => break, + None => return (i, false), Some('"') => { - i = copy_string(chars, i, out); + let (next, terminated) = copy_string(chars, i, out); + i = next; + if !terminated { + return (i, false); + } } Some(&c) => { depth += bracket_delta_brace(c); @@ -146,7 +205,7 @@ fn copy_interpolation(chars: &[char], start: usize, out: &mut String) -> usize { } } } - i + (i, true) } /// Like [`bracket_delta`] but only braces matter when tracking interpolation @@ -205,6 +264,39 @@ mod tests { assert_eq!(line.content, "x = 1 // note with spaces"); } + #[test] + fn a_string_that_spans_lines_becomes_one_logical_line() { + // Two physical lines, one literal: the newline and the interior double + // spaces belong to the value, so they survive scanning untouched, and + // the code after the closing quote is normalised as usual. + let lines = scan_source("print(\"a b\nc d\") \nx = 1\n"); + assert_eq!(lines.len(), 3, "{lines:?}"); + assert_eq!( + lines.first().map(|l| l.content.as_str()), + Some("print(\"a b\nc d\")") + ); + assert_eq!(lines.first().map(|l| l.open_delta), Some(0)); + assert_eq!(lines.get(1).map(|l| l.content.as_str()), Some("x = 1")); + } + + #[test] + fn an_interpolation_left_open_at_the_line_end_keeps_the_literal_open() { + // `"${` with no closing brace means the literal continues: the next + // physical line is still inside it. + let lines = scan_source("print(\"v=${ f(\nx) } end\")\n"); + assert_eq!(lines.len(), 2, "{lines:?}"); + assert_eq!( + lines.first().map(|l| l.content.as_str()), + Some("print(\"v=${ f(\nx) } end\")") + ); + } + + #[test] + fn a_single_line_string_does_not_open_one() { + assert!(!scan_line(r#"print("a")"#).open_string); + assert!(scan_line(r#"print("a"#).open_string); + } + #[test] fn blank_and_comment_classification() { assert!(scan_line(" ").is_blank()); diff --git a/crates/osprey-fmt/tests/corpus.rs b/crates/osprey-fmt/tests/corpus.rs index 2070baa7..e6edffcb 100644 --- a/crates/osprey-fmt/tests/corpus.rs +++ b/crates/osprey-fmt/tests/corpus.rs @@ -6,10 +6,11 @@ //! second pass changes nothing) and **meaning-preserving** (the formatted text //! reparses to the very same AST). Every corpus file must parse: silently //! skipping one would leave a formatter regression outside this audit. -#![expect( - clippy::panic, - reason = "test assertions: a read or re-format failure here is a test failure, not a production panic" -)] +//! +//! Both halves are real only because a failed meaning-preservation guard is an +//! error (`osprey_fmt::DECLINED`) rather than the input returned verbatim — +//! until plan 0019 closed that, "declined to format" and "already formatted" +//! were the same observation here. use std::fs; use std::path::{Path, PathBuf}; @@ -63,32 +64,39 @@ fn is_generated(path: &Path) -> bool { path.ends_with("examples/projects/modules/src/web/bundle.ospml") } -/// Format every corpus source of one extension, asserting idempotency and a clean -/// reparse. Returns `(processed, changed)`. -fn check_extension(ext: &str) -> (usize, usize) { +/// Format every corpus source of one extension, collecting **every** file that +/// fails rather than stopping at the first: one run reports the whole blast +/// radius of a formatter regression. Returns `(processed, failures)`. +fn check_extension(ext: &str) -> (usize, Vec) { let mut processed = 0; - let mut changed = 0; + let mut failures = Vec::new(); for path in sources(ext) { let display = path.display(); - let src = fs::read_to_string(&path).unwrap_or_else(|e| panic!("read {display}: {e}")); - let key = path.to_string_lossy(); - let once = format_for_path(&key, &src) - .unwrap_or_else(|errors| panic!("format {display}: {errors:?}")); + let Ok(src) = fs::read_to_string(&path) else { + failures.push(format!("{display}: unreadable")); + continue; + }; processed += 1; - if once != src { - changed += 1; + let key = path.to_string_lossy(); + match format_for_path(&key, &src) { + Err(errors) => failures.push(format!("{display}: format: {errors:?}")), + Ok(once) => match format_for_path(&key, &once) { + Err(errors) => failures.push(format!("{display}: re-format: {errors:?}")), + Ok(twice) if twice != once => { + failures.push(format!("{display}: not idempotent")); + } + Ok(_) => {} + }, } - let twice = - format_for_path(&key, &once).unwrap_or_else(|e| panic!("re-format {display}: {e:?}")); - assert_eq!(once, twice, "formatting is not idempotent for {display}"); } - (processed, changed) + (processed, failures) } #[test] fn default_corpus_formats_idempotently() { - let (processed, _changed) = check_extension("osp"); + let (processed, failures) = check_extension("osp"); assert!(processed > 0, "no .osp sources were processed"); + assert!(failures.is_empty(), "{}", failures.join("\n")); } #[test] @@ -106,8 +114,9 @@ fn ml_corpus_formats_idempotently() { "ML formatter corpus omitted {required}" ); } - let (processed, _changed) = check_extension("ospml"); + let (processed, failures) = check_extension("ospml"); assert!(processed > 0, "no .ospml sources were processed"); + assert!(failures.is_empty(), "{}", failures.join("\n")); } #[test] @@ -123,7 +132,8 @@ fn ml_clause_and_match_surface_forms_are_preserved() { " Some n => n\n", " None => 0\n", ); - let out = format_for_path("forms.ospml", src).unwrap_or_else(|e| panic!("{e:?}")); + let out = format_for_path("forms.ospml", src).unwrap_or_default(); + assert!(!out.is_empty(), "forms.ospml did not format"); assert_ne!(out, src, "the irregular layout must be reformatted"); assert!( out.contains("type Choice = None | Some int"), @@ -144,6 +154,6 @@ fn ml_clause_and_match_surface_forms_are_preserved() { out.contains("\n Some n => n\n"), "match layout changed: {out}" ); - let twice = format_for_path("forms.ospml", &out).unwrap_or_else(|e| panic!("{e:?}")); + let twice = format_for_path("forms.ospml", &out).unwrap_or_default(); assert_eq!(out, twice, "Plan 0019 forms are not idempotent"); } diff --git a/crates/osprey-syntax/src/positional.rs b/crates/osprey-syntax/src/positional.rs index d02cde02..afd65955 100644 --- a/crates/osprey-syntax/src/positional.rs +++ b/crates/osprey-syntax/src/positional.rs @@ -87,3 +87,73 @@ pub(crate) fn construct(name: &str, args: Vec) -> Option { .collect(), }) } + +#[cfg(test)] +mod tests { + use osprey_ast::{Expr, InterpolatedPart, Program, Stmt}; + + /// Slot names of the `Node` construction bound to `name`, looking through + /// one level of `${…}` interpolation. `None` when the binding is absent or + /// its value is not a construction at all — the shape a lost table + /// produces, since an unfolded spine stays an [`Expr::Call`]. + fn node_slots<'p>(program: &'p Program, name: &str) -> Option> { + let bound = program.statements.iter().find_map(|stmt| match stmt { + Stmt::Let { + name: declared, + value, + .. + } if declared == name => Some(value), + _ => None, + })?; + let expr = match bound { + Expr::InterpolatedStr(parts) => parts.iter().find_map(|part| match part { + InterpolatedPart::Expr(expr) => Some(expr), + InterpolatedPart::Text(_) => None, + })?, + other => other, + }; + match expr { + Expr::TypeConstructor { + name: ctor, fields, .. + } if ctor == "Node" => Some(fields.iter().map(|f| f.name.as_str()).collect()), + _ => None, + } + } + + /// Lowering re-enters itself: a `${…}` fragment is re-parsed as a whole + /// mini-program, and that program declares no types. Without + /// [`super::install`]'s outermost guard the fragment's empty table would + /// replace the enclosing unit's, so the identical `Node(Leaf, Leaf)` would + /// fold to a construction outside a string and stay a call inside one — + /// and, because the fragment's [`super::Scope`] clears on drop, stay a call + /// for every statement after it too. + #[test] + fn an_interpolated_fragment_folds_against_the_enclosing_units_constructors() { + let parsed = crate::parse_program(concat!( + "type Tree = Leaf | Node(Tree, Tree)\n", + "let before = Node(Leaf, Leaf)\n", + "let inside = \"${Node(Leaf, Leaf)}\"\n", + "let after = Node(Leaf, Leaf)\n", + )); + assert!(parsed.errors.is_empty(), "{:?}", parsed.errors); + let slots = Some(vec!["0", "1"]); + assert_eq!(node_slots(&parsed.program, "before"), slots, "before"); + assert_eq!(node_slots(&parsed.program, "inside"), slots, "inside"); + assert_eq!(node_slots(&parsed.program, "after"), slots, "after"); + } + + /// The other half of the scope: the table belongs to the unit being + /// lowered, not to the thread. Both parses run on this one test thread, so + /// a table that outlived its [`super::Scope`] would fold the second unit's + /// undeclared `Node` against the first unit's declaration. + #[test] + fn a_units_table_does_not_outlive_its_lowering() { + let declared = crate::parse_program(concat!( + "type Tree = Leaf | Node(Tree, Tree)\n", + "let t = Node(Leaf, Leaf)\n", + )); + assert_eq!(node_slots(&declared.program, "t"), Some(vec!["0", "1"])); + let undeclared = crate::parse_program("let t = Node(Leaf, Leaf)\n"); + assert_eq!(node_slots(&undeclared.program, "t"), None, "stale table"); + } +} diff --git a/crates/osprey-syntax/tests/module_equiv.rs b/crates/osprey-syntax/tests/module_equiv.rs index fb3b7643..2e025783 100644 --- a/crates/osprey-syntax/tests/module_equiv.rs +++ b/crates/osprey-syntax/tests/module_equiv.rs @@ -9,22 +9,7 @@ fn canonical(source: &str, flavor: Flavor) -> String { "{flavor} syntax errors: {:?}", parsed.errors ); - scrub_positions(&format!("{:?}", parsed.program)) -} - -fn scrub_positions(debug: &str) -> String { - let mut out = String::with_capacity(debug.len()); - let mut rest = debug; - while let Some(start) = rest.find("Position {") { - out.push_str(&rest[..start]); - rest = &rest[start..]; - match rest.find('}') { - Some(end) => rest = &rest[end.saturating_add(1)..], - None => break, - } - } - out.push_str(rest); - out.replace("position: Some()", "position: None") + osprey_ast::canonical::without_positions(&parsed.program) } fn assert_equivalent(default: &str, ml: &str) { diff --git a/docs/plans/0019-ml-elegance.md b/docs/plans/0019-ml-elegance.md deleted file mode 100644 index 0dc56ade..00000000 --- a/docs/plans/0019-ml-elegance.md +++ /dev/null @@ -1,523 +0,0 @@ -# Plan 0019 — ML Flavor Elegance - -> **Superseded safety decision (2026-07-26).** Phase 2's shipped -> `[ARITH-PLAIN]` decision is retained below only as implementation history. It -> is no longer a language contract. The normative replacement is -> [ARITH-CHECKED](../specs/0013-ErrorHandling.md#arithmetic-and-result--arith-checked): -> integer `+`, `-`, `*`, unary negation, and `abs` are checked `Result` -> operations, and no context may implicitly erase a `Result`. Any implementation -> or corpus state described below that silently wraps is a known violation to be -> migrated, not permitted behavior. - -**Status:** **Mostly complete — not retired.** Phases 1.1–1.5, 2 and 3 are -implemented and verified. -Integer `+ - *` return checked `Result` values, `%` is zero-checked, -`checkedAdd` / `checkedSub` / `checkedMul` exist in both flavors, `_` is a legal -parameter in both flavors, positional variant payloads are shared core, and ML -inline unions, clause sets, grouped patterns and `?:` all work. -`benchmarks/cases/binarytrees/binarytrees.ospml` is 6 code lines and emits -byte-identical LLVM IR to its Default twin — **true again as of 2026-07-30**, and -now guarded: it had silently stopped compiling under `[ARITH-CHECKED]` (four -`cannot unify int with Result` errors) because no test -type-checked a `.ospml` outside `tests/`. See -[§Outstanding](#outstanding-2026-07-30) for what still is not done. Specs -[0024 — ML Flavor Syntax](../specs/0024-MLFlavorSyntax.md), -[0013 — Error Handling](../specs/0013-ErrorHandling.md), -[0004 — Type System](../specs/0004-TypeSystem.md) and -[0003 — Syntax](../specs/0003-Syntax.md) carry the shipped surface as normative -text. The same-name binding sweep and whole-corpus `osprey-fmt` audit are also -complete: unreachable adjacent clauses and non-adjacent duplicate definitions -are diagnosed, and every hand-written source under `examples`, `benchmarks`, -and `tests` must parse and format idempotently. - -## Summary - -`benchmarks/cases/binarytrees/binarytrees.ospml` was 22 code lines. Five syntax -and type-system constraints accounted for the removable lines. The work was -split into independently shippable phases. The target was: - -```osprey-ml -type Tree = Leaf | Node Tree Tree - -make 0 = Node Leaf Leaf -make d = Node (make (d - 1)) (make (d - 1)) - -check Leaf = 0 -check (Node l r) = 1 + check l + check r - -print "${range 0 1200 |> fold 0 (\(acc, _) => acc + check (make 13))}" -``` - -`fold`'s callback is flat, not curried, so the lambda takes a pair pattern. -The shipped file is 6 code lines / ~73 tokens, down from 22 lines, and emits LLVM -IR byte-identical to the Default twin `binarytrees.osp`. - -## Evidence - -Measured **before implementation** against the 102 hand-written `.ospml` files -(7,513 LOC) under `examples/` and `benchmarks/`, excluding the generated bundle. -The table is the baseline the phases were sized against; every root cause in it -is now fixed. - -| Root cause | Where | Corpus cost | -|---|---|---| -| `\|` is not a lexeme | `crates/osprey-syntax/src/ml/lexer.rs` (`single_char_operator`) — `unexpected character '|'` | 48 of 54 type declarations exceed two lines; 236 LOC | -| Payload fields must be named | `crates/osprey-ast/src/lib.rs:230-248`, `ml/parser.rs:394` | 124 sites re-type 298 `field = value` pairs | -| Arithmetic is `Result`-typed | `crates/osprey-types/src/expr.rs:736-742` vs strict `push_unify` in `osprey-types/src/pattern.rs:65` | 11 operator wrappers; 112 of 204 signature lines exist only to force auto-unwrap | -| Definition heads take identifiers only | `crates/osprey-syntax/src/ml/parser.rs:878` (`is_binding_head`) | 88 functions shaped `name arg = match arg`, ~600 arm lines | -| `(` is a parse error in pattern position | `crates/osprey-syntax/src/ml/parser.rs:1459` | blocks the fix above | -| ML has no `?:` | `crates/osprey-syntax/src/ml/lexer.rs` rejects `?` outright, though Default's `?:` works | 207 `Success v => v` / `Error m => fallback` blocks in 38 files, ~620 LOC (15–20% of all hand-written ML) | - -### Arithmetic result wrappers - -`gen_arith` (`crates/osprey-codegen/src/expr.rs`) emitted a bare -`add i64` / `sub i64` / `mul i64` / `srem i64` and unconditionally `make_ok`ed -the result. No overflow intrinsic, no zero check. Reproduced then: - -``` -let big = 9223372036854775807 -print("overflow: ${big + 1}") // -9223372036854775808 — silent two's-complement wrap -print("modzero: ${10 % 0}") // garbage — undefined `srem` by zero -``` - -`MathError::Overflow` was unreachable and `%`-by-zero was undefined behaviour; -the corpus paid 11 wrapper functions and 112 signature lines although codegen -performed no overflow check. The historical phase made `%` zero-checked and -added `checkedAdd` / `checkedSub` / `checkedMul`, but still let bare `+` wrap. -That intermediate behavior is no longer permitted: `[ARITH-CHECKED]` makes -integer `+`, `-`, and `*` checked `Result` operations by default. - -The wrapper also caused one heap allocation per arithmetic operation. -`make_ok` → `make_result` -(`crates/osprey-codegen/src/result.rs:22-40`) calls `malloc_struct`, so -`fn addup(a: int, b: int) -> int = a + b` emitted: - -```llvm -%r0 = add i64 %a, %b -%r3 = call i8* @osp_alloc_tagged(i64 %r2, i64 1025) ; heap-allocate the Result -%r5 = getelementptr ... i32 0, i32 0 -store i64 %r0, i64* %r5 ; store payload -store i8 0, i8* %r6 ; store discriminant -``` - -— one `add`, one runtime allocation, three stores, then an immediate unwrap back -to `i64`. Every `+`, `-`, `*` and `%` paid this cost. The arithmetic-dominated -benchmark cases (`fib`, `ackermann`, `nestedloop`, `collatz`, `binarytrees`) -allocated once per operation. Phase 2 temporarily removed that representation -from `+ - *`; the later safety correction restored their checked `Result` -contract. Performance work must optimize that safe representation rather than -erase its failure channel. - -### Defects fixed along the way - -- **`bind_variant_fields`** (`crates/osprey-codegen/src/pattern.rs`) resolved - each pattern binder against the variant layout **by name**, so `Node left right` - worked only because the binders happened to equal the declared field names; - renaming them typechecked and then died at `codegen: unknown name`. - Default-flavor `Ctor(x)` had the same hole: `osprey-types/src/pattern.rs` - bound `sub_patterns` positionally while `pattern_ctor` discarded them. - **This entry overstated its own fix**, and the correction is recorded in - [§Outstanding](#outstanding-2026-07-30): binding by slot was made conditional - on the variant being *declared* positionally, so the by-name resolution — and - the disagreement with the checker — survived for every named payload in both - flavors until 2026-07-30. -- **`finish_phi`** (`crates/osprey-codegen/src/pattern.rs`) returned - `Value::unit()` when arm LLVM types disagreed instead of erroring, converting a - class of type-system mistakes into silently-unit expressions. It now errors, - except where the value is genuinely discarded — statement position, or a - `-> Unit` function body — tracked by a `value_discarded` flag on the codegen - builder. -- **Arithmetic swallowed operand errors.** An arithmetic expression with a - `Result`-typed operand unwrapped it instead of propagating, and fabricated a - success payload on the error path: `toString((10 / 0) + 1.0)` evaluated to - `Success(1.0)`, not `Error(division by zero)`. The specs said "if any - sub-expression errors, the chain errors"; that was not true. A `Result`-typed - operand now propagates, and `(10 / 0) + 1.0` yields `Error(division by zero)`. - -## Phase 1 — pure sugar - -Zero AST change, zero type-checker change. **Shipped.** Every file touched is -under `crates/osprey-syntax/src/ml/`, except the Default-flavor half of -`[PARAM-WILDCARD]` and the LLVM parameter naming it needs (1.3). Each item was -independently mergeable, in this order. - -1. **`[FLAVOR-ML-PATTERN-GROUP]`** — one `TokKind::LParen` arm in `fn pattern()` - (`ml/parser.rs`). Grouping erases at parse time; nested constructor patterns - and or-patterns get explicit diagnostics. ~6 LOC. **Superseded for the - comma case:** `(a, b)` is now an implemented tuple pattern - ([FLAVOR-ML-TUPLE](../specs/0024-MLFlavorSyntax.md#match), - [PATTERN-TUPLE](../specs/0007-PatternMatching.md#tuple-patterns--pattern-tuple)). -2. **`[FLAVOR-ML-UNION-INLINE]`**, named payloads only — `TokKind::Pipe` in - `ml/token.rs`; `|` in `single_char_operator` (`ml/lexer.rs:410`) **after** - `two_char_operator` so `||` and `|>` keep maximal munch; a union arm in - `type_decl_after_keyword` (`ml/parser.rs:277-281`) before the manifest-alias - fallback, with a forward-progress guard. Keep `|` out of `infix_bp` - (`ml/parser.rs:74`). Commit to the union branch only on an uppercase head so - `type Id = int` still aliases. Ship the "or-patterns are not supported" - diagnostic with it — once `|` lexes, users try `Leaf | Node l r =>` and - deserve better than a generic parse error. ~80 LOC. -3. **`[PARAM-WILDCARD]` — shared core, both flavors.** ML: `_` in `one_param` - (`ml/parser.rs:837`); `flat_params` / `curry_params` (`ml/lower.rs:795`) emit a - `Parameter` with a generated unspellable name so repeated `_`s cannot collide. - Default: `parameter` (`tree-sitter-osprey/grammar.js`) admits `_` beside - `identifier`, and the Default lowerer emits the *same* generated name — without - it `\(acc, _) => …` has no [FLAVOR-IR-EQUIV](../specs/0023-LanguageFlavors.md#cross-flavor-equivalence-tests) - twin, since `|acc, _| => …` would not parse. `Expr::Lambda.position` must stay - unique — inference publishes the resolved lambda type under it - (`osprey-ast/src/lib.rs:664-666`). ~20 LOC. - **Refinement shipped with this item:** LLVM parameters are named - **positionally** (`%$p0`, `%$p1`) rather than after their source identifier; - DWARF still carries the source name. That is what makes ML and Default twins - byte-identical when the two authors spell a parameter differently, and it is - the only way a generated clause-set scrutinee — which has no source spelling — - can match its twin. [FLAVOR-IR-EQUIV] rests on it. -4. **`[FLAVOR-ML-CLAUSES]`** — `is_binding_head` (`ml/parser.rs`) accepts - literal / constructor / `_` / `(` before the `=`, still requiring a top-level - `Eq` before the newline; `MlItem::Binding`'s head becomes `Vec` in - `ml/cst.rs`. The merge is a **CST-to-CST pre-pass** in the new - `crates/osprey-syntax/src/ml/clauses.rs`, which rewrites each run of adjacent - same-name same-arity clauses into the plain parameter-list-over-`match` form - before lowering — so the shared core never sees a clause set and the emitted - node is exactly the Default twin's `fn make(d) = match d { … }` under - [FLAVOR-IR-EQUIV](../specs/0023-LanguageFlavors.md). Exactly one refutable - column is supported; selecting on two columns is a diagnostic. The generated - scrutinee needs no source spelling, because LLVM parameters are named - positionally (1.3). Each arm carries its own clause `Position` per - [FLAVOR-LOWER-CONTRACT] rule 2 or exhaustiveness errors land on the wrong - line. ~120 LOC. -5. **ML `?:`** — the Result default the Default flavor already has. `?:` in - `two_char_operator` (`ml/lexer.rs`, matched before `?` and `:` so maximal - munch holds against the type-signature colon), in `infix_bp` - (`ml/parser.rs:74`), lowered in `ml/lower.rs` to the **same shape Default - emits** — `lower_ternary` (`default/expr.rs:191-205`) reuses the scrutinee as - the `then` branch of an `Expr::Match` carrying two `Pattern::Literal(Bool)` - arms. Not a `Success`/`Wildcard` pair: that is a different node and breaks - [FLAVOR-IR-EQUIV](../specs/0023-LanguageFlavors.md#cross-flavor-equivalence-tests) - against the Default twin - ([PATTERN-RESULT-DEFAULT](../specs/0007-PatternMatching.md#result-default---pattern-result-default)). - The scrutinee must therefore be a `Result` or a `bool` — `5 ?: -1` is - `cannot unify int with bool`, in both flavors alike. **No new operator, no - AST change, no tree-sitter change, no Default-flavor work** — - `let v = intDiv(a: 10, b: 2) ?: -1` printed `5` in Default while the same - line in a `.ospml` died at `unexpected character '?'`; the spelling is now - identical in both flavors, right-associative, binding below `||`. ~40 LOC. - -**Result: binarytrees 22 → 14 lines**, and ~620 LOC removable corpus-wide by -`?:` alone once the corpus migrates. - -### Phase 1 corpus sweep - -Two same-name bindings compiled clean and last-wins silently before the merge: -`f x = 1` / `f x = 2` printed `2` with no diagnostic. The completed sweep now -rejects every clause after an irrefutable binder or wildcard, including adjacent -all-irrefutable duplicates, with `unreachable clause`. Non-adjacent same-name -bindings remain separate through parsing and the type checker reports -`duplicate definition`, so a scattered function can never acquire -order-dependent clause grouping. - -## Phase 2 — [ARITH-PLAIN] (historical, superseded) - -This section records the former type-system implementation; it required no AST -change. Its contract is superseded by -[ARITH-CHECKED](../specs/0013-ErrorHandling.md#arithmetic-and-result--arith-checked). - -- `int_arithmetic` (`crates/osprey-types/src/expr.rs`) returns `int` for two int - operands and `float` when either operand is float, for `+ - *`; `gen_arith` - (`crates/osprey-codegen/src/expr.rs`) drops the `make_ok` wrap. -- `/` is unchanged: `Result`, divide-by-zero checked. -- `%` keeps its `Result` type — `Result` for int operands, - `Result` when a float operand is present — and **gained a - real zero check**, replacing the undefined `srem`. -- Builtins `checkedAdd` / `checkedSub` / `checkedMul` exist in both flavors, - registered in `crates/osprey-types/src/builtins.rs` and documented in - `builtin_docs_lang.rs`, signature `(a: int, b: int) -> Result`, - lowered through `llvm.s{add,sub,mul}.with.overflow.i64`, following the existing - `intDiv` precedent. These builtins report overflow; checking is opt-in at the - call site. -- Specs 0004 and 0013 reflect this. Auto-unwrap context 1 ("nested arithmetic") - ceases to exist — five contexts become four. -- Every `.expectedoutput` showing `Success(n)` from `toString` over an - arithmetic expression was regenerated. - -**Historical contract (superseded):** operators whose only failure mode was -overflow returned the plain type and wrapped, while `/` and `%` kept `Result`. -This paragraph records the removed decision; it is not valid Osprey semantics. - -**Result: binarytrees 14 → 6 lines.** Corpus-wide, 11 operator wrappers were -deleted, 112 signature lines became removable, and one heap allocation per -arithmetic operation was eliminated. - -### Rejected: the match-arm `Result` join - -Joining match arms of `Result` with `T` was rejected for three reasons: - -1. **Non-principal.** The checker is an eager unifier with no deferred - constraints. When an arm's pruned type is still `Type::Var` the join must - guess between unwrapping and widening, and the guess propagates. Keeping - auto-unwrap out of plain `unify` is what prevents this today. -2. **It silently miscompiled.** `gen_arith` returned a `Result` struct, so a - joined match mixed `i64` and Result-shaped arms — and `finish_phi` returned - `Value::unit()` rather than erroring on mismatched arm types. Accepting the - join at the type level without a checker-published per-arm unwrap table - yielded a match that silently evaluated to unit. -3. **It does not fix the target program.** `fold 0 (\(acc, _) => acc + check (make 13))` - needs the lambda body to unify under a `Con` argument, where - `try_unwrap_result` (`crates/osprey-types/src/unify.rs:82-99`) deliberately - does not fire. - -## Phase 3 — `[TYPE-UNION-POSITIONAL]`, shared core - -The one AST change, and the correctness fix. - -- A positional payload slot is a **field whose declared name is its decimal - index** (`"0"`, `"1"`). A decimal string is not a valid identifier in either - flavor, so a positional payload can never be reached by name (`t.0` does not - parse) and a generated slot name can never collide with a user-written field. - `osprey_ast::{positional_field_name, is_positional_field}` are the single - definition and its inverse. This replaced the proposed `positional: bool` flag - on `TypeField`, which would have had to be plumbed through both `CtorInfo` - types and `CtorView`. -- The positional alternative in the `variant` rule of - `tree-sitter-osprey/grammar.js`, so Default spells `Node(Tree, Tree)`. -- Positional **construction** folds in each frontend — in ML, - `lower_application` folding a saturated `App(Ident(Ctor), args)` into - `Expr::TypeConstructor` off a constructor-arity pre-pass precedented by the - existing `BOUND_NAMES` collector, so it does not breach [FLAVOR-BOUNDARY] — - but both frontends call the same shared table in the new - `crates/osprey-syntax/src/positional.rs` (`install` / `construct`), so the - emitted `Expr::TypeConstructor` is identical by construction rather than by - review. -- `pattern_ctor` / `bind_variant_fields` bind `sub_patterns` **by slot**. - -This is shared core, not ML sugar. [FLAVOR-LOWER-CONTRACT] rule 5 forbids a -flavor-only node shape, and [FLAVOR-IR-EQUIV] requires a Default twin for every -`.ospml` — so the sugar-only route would force twins to spell -`type Tree = Leaf | Node { _0: Tree, _1: Tree }`, putting synthesized -identifiers into checked-in fixtures, making `t._0` legal and undocumented, and -leaking `_0` into every type-error message. - -Two rules the spec states and the implementation enforces: -constructors do not curry (`Node Leaf` is an arity error, since -`Expr::TypeConstructor` has no partial form); and a positional pattern binds by -column against **every** variant, named payload included. The second rule was -originally written as "positionally **only** against positionally-declared -variants, so no existing `.ospml` changes meaning" — see -[§Outstanding](#outstanding-2026-07-30) for why that scoping was withdrawn: it is -the declaration-based reading that split the checker from codegen. The pre-pass sees only ctors declared in the -compilation unit — an imported ctor falls back to the named form or is -diagnosed, never silently mis-lowered as a curried call. - -**Result: the 6-line target at ~73 tokens, IR-identical to its Default twin.** -Corpus-wide, 298 `field = value` pairs become deletable as the corpus migrates. - -## Compatibility budget - -**Constraint: slight breaking changes are acceptable; a reassembly of the flavor -is not. Most existing samples must keep compiling.** Measured before -implementation against the 208 corpus files (103 `.ospml`, 105 `.osp`): - -| Phase | Breaking? | Corpus impact | -|---|---|---| -| 1.1 `(P)` patterns | No | `(` was a parse error in pattern position | -| 1.2 inline `\|` unions | No | `\|` did not lex; the layout form stays valid | -| 1.3 `_` params | No | `_` was a parse error in parameter position | -| 1.4 clauses | **Yes, narrow** | see below | -| 1.5 ML `?:` | No | `?` did not lex | -| 2 `[ARITH-PLAIN]` | **Yes** | 23 files, 8 `.expectedoutput` | -| 3 positional payloads | No | new declaration form; named variants keep by-name binding | - -Phases 1.1–1.3, 1.5 and 3 are **purely additive by construction**: every token -they introduce was a lexical or parse error before, so no existing program could -be using it. Verified — the only `|` and `?` characters in the `.ospml` corpus are -inside string literals and comments, which the shared `crate::strings` scanner -handles and neither lexer change touches. - -**Withdrawn (2026-07-30):** this paragraph used to add that positional payloads -are additive because a bare `C a b` against a **named**-payload variant "keeps -its existing by-name meaning; that asymmetry is the compatibility guarantee, not -an oversight." The asymmetry was the defect, not the guarantee — it is what let -the checker read a column while codegen read a name. `C a b` now binds by column -against every variant. The only programs whose meaning changes are those whose -binders are field names in an order *other* than the declared one, which -previously bound by name and now bind positionally; nothing in the 160-program -corpus did that, because by-name and by-column agree for every spelling that used -to work. - -**Phase 2 is the only broad break**, and it is mechanical in the shrinking -direction. 23 of 208 files matched `Success`/`Error` over a `+ - *` expression -(76 arm sites), e.g. `comprehensive_math.osp:10`: - -```osprey -2 => match base * base { Success { value } => value Error { message } => 0 } -2 => base * base // migrated -``` - -No logic changes; each site loses a wrapper. 8 `.expectedoutput` files carried -`Success(n)` from `toString` over arithmetic and were regenerated. 89% of the -corpus was untouched. - -**Phase 1.4 is the one behavioural change to watch.** Two same-name bindings -formerly compiled clean and last-wins silently (`f x = 1` / `f x = 2` printed -`2`). They are now rejected: an adjacent binding after an irrefutable clause -reports `unreachable clause`, while a non-adjacent same-name binding reports -`duplicate definition`. - -Nothing in phases 1–3 removes an existing form. The ML layout union, layout -record construction, named-field payloads, and the explicit `match` all remain -normative and valid; the new forms sit beside them. - -## Completion - -Phases 1.1–1.5, 2 and 3 and the defect fixes are implemented and verified. The -completion audit enforces: - -- unreachable adjacent clauses and non-adjacent duplicate definitions; -- parse-clean, meaning-preserving, idempotent formatting across every - hand-written `.osp` and `.ospml` source under `examples`, `benchmarks`, and - `tests`; -- preservation of inline unions, positional construction, grouped and list - equation clauses, `_`, `?:`, checked arithmetic, and explicit `match` through - formatting; and -- byte-identical LLVM IR for every Default/ML twin under `tests` **and** - `benchmarks` (`cross_flavor_ir_equiv.rs` `flavor_roots`). - -One documented exception to the last bullet: `examples/wasm/studio.{osp,ospml}` -is a twin pair whose IR is **not** identical — Default lowers string concat -through `strcat`/`strcpy`, ML through the format path. `examples/` is not a -`flavor_roots` entry, so the guarantee is scoped to the two roots named above. - -## Outstanding (2026-07-30) - -Found by auditing every checked claim against the tree. None of these block the -shipped syntax; all of them mean this plan is not retired. - -- [x] **`binarytrees.ospml` compiles and is IR-identical to its twin.** It had - not been migrated to `[ARITH-CHECKED]`: four `+`/`-` sites lacked the `?: 0` - their Default twin carries, so `--check` emitted four - `cannot unify int with Result`. Migrated, and the coverage - hole that let it rot is closed — `flavor_roots()` in - `crates/osprey-cli/tests/cross_flavor_ir_equiv.rs` now walks `benchmarks` - as well as `tests` (verified to fail when a `?:` is removed). Still 6 code - lines, still checksum `19659600`. -- [x] **Positional sub-patterns over a *named*-payload variant miscompiled.** - Fixed on the codegen/lowering side; the checker was already right, so - `positional_constructor_destructures_fields` - (`crates/osprey-types/src/pattern.rs`) went from pinning an acceptance - codegen contradicted to pinning one it honours. The rule is now stated by - the **pattern form**, never by the declaration: `Ctor { a, b }` binds each - binder to the field of that name, `Ctor(a, b)` binds column *i* to slot - *i*. - - `bind_variant_fields` (`crates/osprey-codegen/src/pattern.rs`) chose its - mode from the *declaration* — by slot only for a positionally declared - variant — while `osprey-types` bound `sub_patterns` by column for every - variant. Over a named payload the two disagreed. `Wrap(v)` died at - `codegen: unknown name v`; worse, when every binder happened to name a - field in the *wrong* order the disagreement went silent — - `Pair(second, first)` over `Pair { first: string, second: int }` returned - slot 0's string pointer out of an `-> int` function as a `ptrtoint`, so a - well-typed program printed a **raw heap address that changed between - runs**. - - ML had the same defect and reached it through its *only* constructor - destructure: `MlPattern::Ctor` lowered its binders into `fields`, the - named form, so `Pair a b` bound nothing and `Pair second first` bound - backwards relative to its Default twin — a [FLAVOR-IR-EQUIV] hole as well - as a miscompile. ML now lowers through the new shared - `desugar::ctor_pattern`, which is also the single statement of the one - exception: `Success`/`Error` bind by ROLE (`value`, `message`), so they - stay in `fields` in both flavors. - - The named form over a *positionally* declared variant (`Fail { reason }` - against `Fail(string)`) still binds by column, because a synthetic slot - name is unspellable and no binder can ever match one. - - Covered by three `osprey-codegen` tests over the three shapes, and - end-to-end in both flavors by `feature_omnibus.test.{osp,ospml}`, whose - `swapped` row pins that the column beats a colliding field name. -- [x] **`5 ?: -1` was accepted.** Now rejected with - `` `?:` needs a Result on its left, found int ``, enforcing - [PATTERN-RESULT-DEFAULT](../specs/0007-PatternMatching.md)'s "the scrutinee - must be a `Result` … never reinterprets a plain value as `Success`". - `?:` desugars to a `Success`/`Error` match, so it silently inherited the - *ordinary* match auto-wrap rule — any value may be matched as if wrapped in - `Success` — and the fallback became unreachable dead code. Only the - desugarer's unspellable payload binder separates the two forms, so it moved - to `osprey_ast::RESULT_DEFAULT_PAYLOAD` where the checker can see it; - `reject_plain_result_default` (`crates/osprey-types/src/pattern.rs`) fires - on that marker alone, leaving a hand-written `Success` arm's auto-wrap - intact (both directions are pinned by tests). An unresolved scrutinee is - exempt, since this checker unifies eagerly and a variable may still become - a `Result`. - - Phase 1.5's prose above is **stale on two counts**: `?:` lowers through - `desugar::result_default`, not the boolean pair, so a `bool` scrutinee is - not accepted either, and the diagnostic is not - `cannot unify int with bool`. - - Corpus impact across all 160 programs was **two files**, the - `result_chain_unary_stress` twins, which wrote `abs((-N) ?: 0)` at 20 - sites on the assumption that unary negation is checked. It is — for a - *variable* (`-x` is `Success(-5)`) — but a negative literal is folded, so - `-1` is a plain `int` and the `?: 0` was dead. Removed; both twins still - report 112/112. - - Guarded end-to-end by - `examples/failscompilation/result_default_on_plain_value.ospo`. -- [x] **`finish_phi`'s `match arms disagree on type` error now has a test.** - `match_arms_of_different_physical_types_are_rejected_not_unitised` - (`crates/osprey-codegen/src/lib.rs`) pins it. Like the `select` rejection it - sits beside, this branch has no surface syntax of its own — the checker - rejects mismatched arms first (`cannot unify int with string`), so it is - reachable only by handing an AST straight to `compile_program`, which is - what `compile_err` is for. Without it nothing failed if `finish_phi` went - back to returning `Value::unit()` and silently turning type errors into unit - expressions. -- [ ] **The interpolation-fragment positional-table scoping guard has no test.** - `crates/osprey-syntax/src/positional.rs` (`DEPTH`/`Scope`): the behaviour is - real but nothing fails if the guard is deleted. A cheap golden addition. -- [ ] **The formatter corpus idempotency assertion is partly self-fulfilling.** - `format_source` silently returns its input when `preserves_meaning` fails, - so `crates/osprey-fmt/tests/corpus.rs` cannot distinguish "formatted - identically" from "declined to format". The parse-clean half of the - guarantee is real; the idempotency half needs the bail to be observable. - -## TODO - -- [x] Phase 1.1 — `[FLAVOR-ML-PATTERN-GROUP]`: `LParen` arm in `fn pattern()`, nested-constructor and or-pattern diagnostics -- [x] Phase 1.2 — `[FLAVOR-ML-UNION-INLINE]`: `TokKind::Pipe`, lexer order, union arm, or-pattern diagnostic -- [x] Phase 1.3 — `[PARAM-WILDCARD]`: `_` param with generated name, both flavors; positional LLVM parameter naming -- [x] Phase 1.4 — `[FLAVOR-ML-CLAUSES]`: pattern heads, CST change, `ml/clauses.rs` CST-to-CST clause-merge pre-pass, per-clause spans -- [x] Phase 1.5 — ML `?:`: lex and parse the Result default the Default flavor already implements -- [x] Phase 1.x — corpus sweep completed. Adjacent clauses after a binder or - wildcard now report `unreachable clause`; adjacent all-irrefutable heads - report the same; non-adjacent same-name functions report - `duplicate definition`. The full formatter corpus parses cleanly. -- [x] Phase 2 — `[ARITH-PLAIN]`: `int_arithmetic`, `gen_arith`, `%` zero check, `checked*` builtins, `.expectedoutput` regeneration -- [ ] Phase 2 — re-run `make bench` and refresh `website/src/benchmarks.md`. - **This item was checked in error, and its claim is now false.** It held only - under the superseded `[ARITH-PLAIN]` decision. `[ARITH-CHECKED]` restored - the `Result` representation — `int_arithmetic_result` - (`crates/osprey-types/src/expr.rs`) returns `res_math(Type::int())` — so the - per-operation allocation is back: `fn addup(a: int, b: int) = a + b` - compiles to `define { i64, i8, i8* }* @addup(…)` containing two - `call i8* @osp_alloc_tagged` sites. The "~1.5 MB for the six `+ - *`-only - cases" figure therefore describes a compiler that no longer exists, and - `website/src/benchmarks.md` says so itself ("Re-run `make bench` before - drawing current per-case conclusions from this historical table"). - Optimizing the *safe* representation is the follow-up; erasing its failure - channel is not (see §Phase 2 above). -- [x] Phase 3 — `[TYPE-UNION-POSITIONAL]`: decimal-index field names, `grammar.js` variant rule, shared `positional.rs` construction table, `sub_patterns`-by-slot fix -- [x] Defect — `finish_phi` errors on mismatched arm LLVM types unless the value is discarded, instead of returning `Value::unit()` -- [x] Defect — arithmetic propagates a `Result` operand's error instead of unwrapping it and fabricating `Success` (`(10 / 0) + 1.0` → `Error(division by zero)`) -- [x] Defect — a Default interpolation fragment is re-parsed as a nested program mid-lowering, which cleared the positional-constructor table; `positional::install` now scopes to the outermost lowering, so `"${Node(l, r)}"` folds like the same expression outside a string -- [x] Defect — a Default nested constructor sub-pattern (`Node(Node(a, b), c)`) was silently discarded and the arm behaved as `Node(_, _)`; it is now rejected with the ML flavor's diagnostic -- [x] Defect — binding lookahead accepted list-pattern clauses while the parameter parser rejected them; `size [] = 0` and sibling list clauses now parse, merge, format, and execute -- [x] Migrate the `.ospml` corpus per phase — `tests/core/feature_composition/feature_omnibus.test.ospml` mixes - inline unions, `_` parameters, equational - clauses, `?:`, checked arithmetic, and positional construction. The - whole-corpus formatter test requires every `.ospml` to parse and - round-trip idempotently, with an explicit clause-vs-`match` surface-form - regression; the Default twin remains byte-identical at LLVM IR. - Two corrections to this item's original wording: `binarytrees.ospml` was - **not** migrated and did not compile until 2026-07-30 (see §Outstanding), - and `feature_omnibus.test.ospml` carries no **grouped** (parenthesized) - positional pattern — its only positional destructure is an unparenthesized - `Wrapped n =>` inside a `match`. Grouped positional clause *heads* are - exercised end-to-end only by `tests/framework/verdict.test.ospml` - (`andThen (Pass) rest = rest`), which is in `ML_ONLY_STEMS` and so exempt - from IR equivalence — a grouped head in a twinned file would be better - coverage. diff --git a/docs/plans/README.md b/docs/plans/README.md index 7248b756..2ceca979 100644 --- a/docs/plans/README.md +++ b/docs/plans/README.md @@ -21,7 +21,7 @@ checklist and records remaining work with concrete repros. | [0015](0015-generics-and-variance.md) | Generics with `in`/`out` variance & generic effects | frontend/types/codegen (both flavors) | Core + generic-fn-values landed, **and so has the static handler/operation instantiation seam** (`crates/osprey-types/src/effect_rows.rs` — a `Stash` handler cannot discharge `Stash.take`), which this row used to list as remaining. Left: call-site type application (`identity(5)`) and its failscompilation fixture | Mostly done | | [0016](0016-algebraic-effects-and-handlers.md) | Algebraic effects roadmap (resume/handler-values/multi-shot) | effects/types/codegen/runtime | Phases A and C done: tail + single-shot resume, generic effects, multi-shot abort (now covered by a runtime test), fiber-perform race fix, lambda-resume type error — **plus static operation inference, propagation, exact handler discharge and entry-point proof** (`crates/osprey-types/src/effect_rows.rs`, 84 checker tests, 12 must-reject fixtures), which this row used to list as outstanding. Whole-`Result` transport through direct handlers (#183) is fixed and locked, and so are #182 (operands now travel in a heap mailbox, so the 16-argument cliff is gone) and #185 (a managed continuation answer releases under ARC) — both former skips are assertions. Left: handler values (Phase B — **duplicated** in [0013](0013-ml-flavor-frontend.md) Phase 0), wasm effects (D), diagnostics/LSP (E), an open-row variable in `Type::Fun`, and showstopper #184 | High | | [0018](0018-documentation-comments.md) | Documentation comments (both flavors) | ast/syntax/lsp/cli | Phases 1–2 shipped: one structured `DocComment` model, `///` and `(** … *)` both captured on every declaration form, hover renders it, `[Symbol]` links resolve. All of Phase 3 remains — doctest **execution**, user-declaration `--docs` export, and `//!` inner docs (whose `DocScope::Inner` arm is unreachable today) | Medium | -| [0019](0019-ml-elegance.md) | ML flavor elegance (inline unions, equational clauses, ML `?:`, positional payloads; historical plain-arithmetic phase superseded by `[ARITH-CHECKED]`) | frontend/types/codegen (both flavors) | Syntax phases shipped and pinned. Phase 2's silent-wrap decision is historical only; checked-`Result` arithmetic is the shipped contract. `binarytrees.ospml` had silently stopped compiling under `[ARITH-CHECKED]` — migrated, and `cross_flavor_ir_equiv` now walks `benchmarks` so it cannot rot again. The `Wrap(v)`-over-named-payload disagreement is **fixed**: a constructor arm's binders now bind by the *pattern form* (`Ctor { a, b }` by name, `Ctor(a, b)` by column) rather than by the declaration, and ML's only destructure lowers positionally like its Default twin — closing a silent miscompile that returned a payload **pointer** out of an `-> int` function. `?:` now also enforces [PATTERN-RESULT-DEFAULT]'s Result-scrutinee rule, which it had been silently inheriting the ordinary match auto-wrap around. Left: regression tests for two already-fixed defects | Medium | +| ~~0019~~ | ML flavor elegance (inline unions, equational clauses, ML `?:`, positional payloads) | frontend/types/codegen (both flavors) | **Done — plan retired.** Every syntax phase shipped and pinned; the last three items closed together. The positional-table scoping guard has two mutation-proven tests in `crates/osprey-syntax/src/positional.rs`. Making the formatter's meaning-preservation bail observable (`osprey_fmt::DECLINED`, plus a corpus test that reports every failing file) showed `osprey fmt` had been a **silent no-op on 58 corpus files** and fixed both causes: the guard compared source *positions*, which reformatting exists to change (56 files — now compared through the one shared `osprey_ast::canonical::without_positions`, which also replaced two hand-copied scrubbers and caught a flavor asymmetry they masked), and the line scanner lost the "inside a string" fact at a newline, so it reindented the **contents** of multi-line string literals (2 files — real source corruption, stopped only by the silent bail). `make bench` was re-run across 22 cases × 11 languages and `website/src/benchmarks.md` rewritten to what the fresh data supports. Two defects found along the way are **not** fixed and belong to no plan: `xs [0]` silently parses as two statements rather than an index, and `ackermann` on `wasm32` prints nothing where native prints 8189 | — | | [0020](0020-package-manager.md) | Source-derived package registry and manager | package core/CLI/API/WASM web/trust plane | Specs 0029–0032 and a 66-source research corpus are complete; **no implementation started** | Very High | | [0021](0021-osprey-github-action.md) | Osprey GitHub Action (marketplace) | tests/action packaging/release | Spec 0033 written; **no implementation started** — no root `action.yml`, no action `Dockerfile`, no `main.osp`, no GHCR release job, and no corpus program pairs `input()` with JSON parsing. Phase 1 is gated on how a program under test receives stdin: `run_test_corpus.sh` pipes nothing to any of its 160 programs. Phase 5's stated blocker is already gone — `input` reaches wasm32 | High | | [0022](0022-arithmetic-totality-audit.md) | Arithmetic totality audit (float NaN/inf, checked-`Result` gaps) | types/codegen/specs | Audit complete with a sequenced checklist; **F10 landed**, the rest not started. Phase 0 design-independent defects (F1 `!=` under NaN, F5 float-arm unification, F7 unsaturated `fptosi`, F9 silent `inf` literals) precede the float-totality decision | Medium | diff --git a/vscode-extension/client/src/test-explorer.ts b/vscode-extension/client/src/test-explorer.ts index 9543d186..3aa980ca 100644 --- a/vscode-extension/client/src/test-explorer.ts +++ b/vscode-extension/client/src/test-explorer.ts @@ -137,8 +137,10 @@ function collectOutput(stream: Readable): () => string { // truncate verbose test output, and `detached` enables the group kill above. A // spawn failure (e.g. ENOENT) maps to exit -1 with the message in stderr. // Cancellation kills the process tree AND settles the promise immediately, so -// a run always reaches its end even if the child were to linger. Exported: the -// profiler command ([PROF-VSCODE-FLAME]) launches the CLI through it too. +// a run always reaches its end even if the child were to linger. The child's +// stdin is closed at once, so a program that reads input sees EOF rather than +// blocking on a pipe no one writes to. Exported: the profiler command +// ([PROF-VSCODE-FLAME]) launches the CLI through it too. export function runCompiler( command: string, args: readonly string[], @@ -148,6 +150,10 @@ export function runCompiler( ): Promise { return new Promise((resolve) => { const child = spawn(command, [...args], { cwd, env, detached: POSIX }); + // Close the child's stdin immediately: nothing is ever written to it, and a + // compiler that reads stdin (`input()`) would otherwise block forever on a + // pipe that never reaches EOF, hanging the run until it is cancelled. + child.stdin?.end(); const stdout = collectOutput(child.stdout); const stderr = collectOutput(child.stderr); let spawnFailure = ""; diff --git a/vscode-extension/test/suite/test-explorer.test.ts b/vscode-extension/test/suite/test-explorer.test.ts index 1e5d0a13..a09232ea 100644 --- a/vscode-extension/test/suite/test-explorer.test.ts +++ b/vscode-extension/test/suite/test-explorer.test.ts @@ -23,6 +23,7 @@ import { refreshTestFile, registerOspreyTestExplorer, removeTestFile, + runCompiler, requestedItems, scanWorkspaceTestFiles, testFileLabel, @@ -258,6 +259,32 @@ suite("Osprey Test Explorer", () => { }); suite("run", () => { + test("runCompiler closes child stdin so input reaches EOF", async function () { + this.timeout(3000); + const source = new vscode.CancellationTokenSource(); + const cancel = setTimeout(() => source.cancel(), 500); + try { + const result = await runCompiler( + process.execPath, + [ + "-e", + "process.stdin.resume(); process.stdin.on('end', () => process.exit(0));", + ], + fixtureDir, + process.env, + source.token, + ); + assert.strictEqual( + result.exitCode, + 0, + "child waited for stdin EOF until the test cancelled it", + ); + } finally { + clearTimeout(cancel); + source.dispose(); + } + }); + function token(): vscode.CancellationToken { return new vscode.CancellationTokenSource().token; } diff --git a/website/src/_includes/benchmarks-tables.html b/website/src/_includes/benchmarks-tables.html index ab950128..9804174e 100644 --- a/website/src/_includes/benchmarks-tables.html +++ b/website/src/_includes/benchmarks-tables.html @@ -1,6 +1,6 @@ -
0CPU wins (fastest of all)
13.64×CPU vs Rust
15.43×CPU vs C
11.05×CPU vs C# (AOT)
5.49×CPU vs Dart (AOT)
10.60×CPU vs OCaml
7.35×CPU vs Haskell
6.91×CPU vs Rust (wasm)

Osprey is the fastest of all five languages on . Lower is better; ★ marks an Osprey win.

+
0CPU wins (fastest of all)
11.59×CPU vs Rust
13.14×CPU vs C
9.19×CPU vs C# (AOT)
4.69×CPU vs Dart (AOT)
8.91×CPU vs OCaml
6.25×CPU vs Haskell
5.65×CPU vs Rust (wasm)

Osprey is the fastest of all five languages on . Lower is better; ★ marks an Osprey win.

CPU time

-
BenchmarkOspreyOsprey (ARC)Osprey (GC)RustCC# (AOT)Dart (AOT)OCamlHaskellRust (wasm)
ackermann914.6 ms864.2 ms4.949 s128.9 ms130.7 ms130.4 ms184.7 ms110.8 ms64.2 ms144.9 ms
binarytrees1.076 s1.301 s4.806 s726.8 ms356.2 ms127.3 ms124.7 ms52.3 ms16.8 ms810.4 ms
coins611.4 ms573.6 ms3.444 s82.6 ms81.0 ms101.6 ms122.3 ms100.5 ms53.9 ms110.8 ms
collatz480.2 ms463.9 ms2.669 s13.0 ms10.4 ms58.9 ms67.5 ms60.1 ms39.3 ms24.6 ms
coprime390.1 ms373.1 ms2.289 s65.7 ms63.7 ms78.2 ms113.2 ms90.7 ms105.7 ms77.3 ms
digitsum408.3 ms397.7 ms2.458 s5.7 ms5.6 ms16.4 ms29.2 ms18.7 ms32.3 ms19.1 ms
exprtree44.4 ms47.9 ms281.2 ms10.8 ms6.3 ms6.5 ms14.3 ms5.3 ms18.1 ms20.6 ms
factorial237.2 ms224.5 ms1.421 s35.5 ms35.4 ms37.2 ms51.7 ms48.7 ms57.4 ms48.6 ms
fib555.6 ms536.0 ms3.171 s17.6 ms18.4 ms36.6 ms52.2 ms24.2 ms48.0 ms37.3 ms
gcdsum331.1 ms323.4 ms1.996 s79.5 ms79.5 ms86.2 ms110.5 ms101.9 ms106.5 ms92.1 ms
hanoi1.254 s1.244 s7.289 s38.9 ms41.0 ms44.9 ms120.1 ms62.8 ms58.2 ms53.1 ms
isqrt445.2 ms444.3 ms2.717 s11.2 ms10.8 ms17.5 ms34.0 ms21.3 ms45.3 ms23.4 ms
josephus232.3 ms225.6 ms1.413 s33.5 ms33.4 ms35.3 ms43.2 ms41.6 ms45.7 ms45.3 ms
listops6.9 ms7.4 ms24.4 ms1.6 ms1.4 ms3.2 ms11.1 ms2.2 ms16.6 ms12.8 ms
mutual730.0 ms685.5 ms4.563 s13.2 ms12.9 ms21.6 ms329.6 ms28.3 ms40.0 ms30.0 ms
nestedloop866.9 ms862.0 ms5.372 s46.2 ms45.9 ms47.8 ms61.4 ms58.2 ms64.4 ms62.5 ms
pascal963.0 ms962.7 ms5.549 s27.8 ms28.2 ms34.4 ms70.6 ms50.4 ms64.2 ms48.1 ms
powmod687.1 ms679.4 ms4.332 s23.9 ms23.8 ms34.5 ms51.3 ms61.4 ms60.3 ms34.6 ms
primes238.5 ms229.8 ms1.473 s6.9 ms6.6 ms8.8 ms44.9 ms9.1 ms17.9 ms17.3 ms
tak471.4 ms468.8 ms2.567 s33.2 ms33.0 ms35.7 ms82.6 ms45.1 ms68.5 ms99.3 ms
textstats23.8 ms24.8 ms123.2 ms2.0 ms2.1 ms3.7 ms11.8 ms4.0 ms17.8 ms12.8 ms
wordfreq40.9 ms47.8 ms187.4 ms4.5 ms1.5 ms3.3 ms11.5 ms2.6 ms17.8 ms15.7 ms
+
BenchmarkOspreyOsprey (ARC)Osprey (GC)RustCC# (AOT)Dart (AOT)OCamlHaskellOsprey (wasm)Rust (wasm)
ackermann1.382 s860.8 ms5.514 s129.3 ms130.6 ms132.4 ms185.3 ms111.3 ms65.3 mswrong✗145.5 ms
binarytrees1.224 s1.156 s5.346 s743.8 ms362.9 ms128.4 ms128.6 ms52.3 ms17.0 ms1.165 s818.6 ms
coins660.2 ms416.7 ms2.582 s84.5 ms79.8 ms104.4 ms126.0 ms103.3 ms52.3 ms466.5 ms114.0 ms
collatz516.9 ms343.7 ms2.162 s13.4 ms10.8 ms59.3 ms72.7 ms64.6 ms40.2 ms380.3 ms25.4 ms
coprime189.7 ms148.4 ms703.3 ms66.4 ms65.0 ms80.5 ms111.6 ms119.4 ms220.3 ms296.5 ms163.3 ms
digitsum686.9 ms397.9 ms4.629 s6.1 ms6.1 ms21.2 ms32.8 ms19.5 ms29.4 ms280.0 ms18.8 ms
exprtree46.4 ms28.1 ms148.9 ms11.1 ms6.1 ms7.7 ms15.8 ms5.1 ms16.3 ms33.7 ms20.4 ms
factorial35.8 ms35.5 ms35.4 ms35.6 ms35.3 ms37.4 ms51.2 ms48.7 ms53.5 ms44.7 ms48.6 ms
fib1.097 s600.5 ms4.502 s22.7 ms23.4 ms43.3 ms59.8 ms29.5 ms56.5 ms684.9 ms49.4 ms
gcdsum133.9 ms120.1 ms241.2 ms86.1 ms86.5 ms92.8 ms122.0 ms107.7 ms115.0 ms126.5 ms104.3 ms
hanoi1.766 s979.3 ms5.488 s37.5 ms38.5 ms38.7 ms103.9 ms62.9 ms54.4 ms766.1 ms52.3 ms
isqrt563.8 ms414.3 ms3.009 s10.9 ms10.6 ms17.1 ms32.5 ms20.6 ms41.0 ms412.9 ms22.9 ms
josephus380.1 ms222.2 ms1.513 s33.8 ms33.4 ms35.9 ms42.0 ms42.0 ms44.5 ms243.7 ms44.4 ms
listops7.2 ms6.1 ms17.4 ms1.5 ms1.3 ms3.3 ms10.8 ms2.2 ms16.6 ms13.4 ms12.5 ms
mutual19.3 ms18.3 ms19.7 ms13.1 ms12.9 ms21.5 ms335.0 ms29.1 ms40.7 ms40.4 ms30.0 ms
nestedloop870.6 ms503.7 ms3.463 s46.4 ms46.0 ms48.4 ms60.6 ms58.5 ms65.2 ms381.6 ms62.9 ms
pascal1.602 s936.7 ms6.487 s27.9 ms28.2 ms34.1 ms65.2 ms45.1 ms65.0 ms970.5 ms46.9 ms
powmod883.9 ms498.5 ms4.019 s27.4 ms27.5 ms40.1 ms58.8 ms71.1 ms65.4 ms407.8 ms39.5 ms
primes316.4 ms171.6 ms1.257 s7.1 ms7.1 ms10.7 ms52.6 ms10.0 ms18.7 ms144.4 ms21.0 ms
tak598.0 ms363.7 ms2.673 s37.5 ms37.3 ms40.5 ms93.3 ms51.2 ms75.0 ms480.5 ms92.0 ms
textstats23.3 ms16.0 ms75.1 ms2.0 ms2.2 ms3.8 ms11.4 ms4.0 ms16.7 ms25.2 ms14.9 ms
wordfreq37.5 ms40.3 ms141.7 ms4.5 ms1.5 ms3.3 ms10.6 ms2.5 ms16.4 ms45.7 ms15.7 ms

Peak memory

-
BenchmarkOspreyOsprey (ARC)Osprey (GC)RustCC# (AOT)Dart (AOT)OCamlHaskellRust (wasm)
ackermann2056.0 MiB1.9 MiB19.0 MiB1.8 MiB1.6 MiB7.0 MiB14.0 MiB2.6 MiB15.1 MiB
binarytrees2410.8 MiB2.8 MiB18.2 MiB2.1 MiB1.7 MiB16.1 MiB22.5 MiB5.1 MiB11.0 MiB
coins1371.3 MiB1.5 MiB19.1 MiB1.5 MiB1.4 MiB6.8 MiB13.9 MiB2.2 MiB11.1 MiB
collatz1102.2 MiB1.5 MiB20.6 MiB1.5 MiB1.4 MiB6.8 MiB13.9 MiB2.2 MiB11.1 MiB
coprime992.1 MiB1.5 MiB18.6 MiB1.5 MiB1.4 MiB6.8 MiB13.9 MiB2.2 MiB11.1 MiB
digitsum1063.6 MiB1.5 MiB18.8 MiB1.5 MiB1.4 MiB6.8 MiB13.9 MiB2.2 MiB11.1 MiB
exprtree109.4 MiB3.4 MiB18.5 MiB2.6 MiB11.4 MiB15.2 MiB22.5 MiB6.0 MiB11.3 MiB
factorial614.2 MiB1.5 MiB19.6 MiB1.5 MiB1.4 MiB6.8 MiB13.8 MiB2.2 MiB11.1 MiB
fib1373.8 MiB1.5 MiB18.6 MiB1.5 MiB1.4 MiB6.8 MiB13.9 MiB2.2 MiB11.1 MiB
gcdsum870.0 MiB1.5 MiB18.8 MiB1.5 MiB1.4 MiB6.8 MiB13.8 MiB2.2 MiB11.1 MiB
hanoi3085.5 MiB1.5 MiB20.6 MiB1.5 MiB1.4 MiB6.8 MiB14.0 MiB2.2 MiB11.1 MiB
isqrt1198.5 MiB1.5 MiB19.1 MiB1.5 MiB1.4 MiB6.8 MiB13.9 MiB2.2 MiB11.1 MiB
josephus614.2 MiB1.5 MiB18.6 MiB1.5 MiB1.4 MiB6.8 MiB13.9 MiB2.2 MiB11.1 MiB
listops22.2 MiB2.0 MiB14.0 MiB1.6 MiB1.4 MiB7.0 MiB14.3 MiB2.5 MiB11.3 MiB
mutual1996.9 MiB1.5 MiB18.6 MiB1.5 MiB1.4 MiB6.8 MiB13.9 MiB2.2 MiB11.1 MiB
nestedloop2397.0 MiB1.5 MiB18.6 MiB1.5 MiB1.4 MiB6.8 MiB13.9 MiB2.2 MiB11.0 MiB
pascal2459.6 MiB1.5 MiB18.6 MiB1.5 MiB1.4 MiB6.8 MiB13.9 MiB2.2 MiB11.1 MiB
powmod1901.0 MiB1.5 MiB18.6 MiB1.5 MiB1.4 MiB6.8 MiB14.0 MiB2.2 MiB11.1 MiB
primes655.8 MiB1.5 MiB18.5 MiB1.5 MiB1.4 MiB6.8 MiB13.9 MiB2.2 MiB11.1 MiB
tak1162.1 MiB1.5 MiB18.8 MiB1.5 MiB1.4 MiB6.8 MiB13.9 MiB2.2 MiB11.1 MiB
textstats56.7 MiB1.5 MiB14.8 MiB1.6 MiB1.4 MiB6.8 MiB14.0 MiB2.3 MiB11.4 MiB
wordfreq102.0 MiB1.6 MiB18.1 MiB1.6 MiB1.4 MiB6.8 MiB14.0 MiB2.3 MiB11.3 MiB
+
BenchmarkOspreyOsprey (ARC)Osprey (GC)RustCC# (AOT)Dart (AOT)OCamlHaskellOsprey (wasm)Rust (wasm)
ackermann2.0 MiB2.0 MiB21.0 MiB1.8 MiB1.7 MiB7.1 MiB14.0 MiB2.7 MiB15.1 MiBwrong✗
binarytrees1808.5 MiB2.9 MiB20.3 MiB2.2 MiB1.8 MiB16.1 MiB22.5 MiB5.2 MiB11.1 MiB
coins1.5 MiB1.5 MiB20.5 MiB1.6 MiB1.5 MiB6.8 MiB13.9 MiB2.3 MiB11.1 MiB
collatz221.8 MiB1.5 MiB18.5 MiB1.6 MiB1.4 MiB6.9 MiB14.0 MiB2.3 MiB11.1 MiB
coprime1.5 MiB1.5 MiB18.7 MiB1.6 MiB1.4 MiB6.8 MiB14.0 MiB2.3 MiB11.1 MiB
digitsum335.1 MiB1.5 MiB22.0 MiB1.6 MiB1.4 MiB6.9 MiB14.0 MiB2.3 MiB11.1 MiB
exprtree9.1 MiB3.4 MiB18.5 MiB2.7 MiB11.5 MiB15.2 MiB22.5 MiB6.1 MiB11.4 MiB
factorial1.5 MiB1.5 MiB1.5 MiB1.6 MiB1.4 MiB6.8 MiB13.9 MiB2.3 MiB11.1 MiB
fib1.5 MiB1.5 MiB22.4 MiB1.6 MiB1.4 MiB6.8 MiB13.9 MiB2.2 MiB11.2 MiB
gcdsum1.5 MiB1.5 MiB22.3 MiB1.6 MiB1.4 MiB6.9 MiB14.0 MiB2.3 MiB11.1 MiB
hanoi1.5 MiB1.5 MiB22.4 MiB1.6 MiB1.4 MiB6.8 MiB13.8 MiB2.3 MiB11.2 MiB
isqrt779.1 MiB1.5 MiB20.7 MiB1.6 MiB1.4 MiB6.8 MiB13.9 MiB2.3 MiB11.1 MiB
josephus1.5 MiB1.5 MiB18.6 MiB1.6 MiB1.4 MiB6.8 MiB13.8 MiB2.3 MiB11.1 MiB
listops14.4 MiB2.1 MiB12.9 MiB1.7 MiB1.5 MiB7.1 MiB14.3 MiB2.6 MiB11.4 MiB
mutual1.5 MiB1.5 MiB7.3 MiB1.6 MiB1.4 MiB6.9 MiB14.0 MiB2.3 MiB11.1 MiB
nestedloop1.5 MiB1.5 MiB20.2 MiB1.6 MiB1.4 MiB6.8 MiB13.9 MiB2.2 MiB11.1 MiB
pascal1.5 MiB1.5 MiB18.6 MiB1.6 MiB1.4 MiB6.9 MiB13.9 MiB2.2 MiB11.1 MiB
powmod1.5 MiB1.5 MiB20.7 MiB1.6 MiB1.4 MiB6.9 MiB14.0 MiB2.3 MiB11.1 MiB
primes1.5 MiB1.5 MiB19.6 MiB1.6 MiB1.4 MiB6.9 MiB14.0 MiB2.2 MiB11.1 MiB
tak1.5 MiB1.5 MiB20.5 MiB1.6 MiB1.4 MiB6.9 MiB13.9 MiB2.3 MiB11.2 MiB
textstats1.5 MiB1.6 MiB18.6 MiB1.6 MiB1.4 MiB6.8 MiB14.0 MiB2.3 MiB11.4 MiB
wordfreq59.1 MiB1.6 MiB18.0 MiB1.6 MiB1.4 MiB6.8 MiB14.0 MiB2.3 MiB11.4 MiB
diff --git a/website/src/benchmarks.md b/website/src/benchmarks.md index 7a2a35ac..290c9571 100644 --- a/website/src/benchmarks.md +++ b/website/src/benchmarks.md @@ -66,32 +66,38 @@ compiled to a native binary, checked for correct output, then timed. an opt-in safety tier. See [ARITH-CHECKED](/spec/0013-errorhandling/). - **The Rust command disables Rust's overflow checks.** The comparison is deliberately asymmetric: Osprey enforces its checked arithmetic contract - while this Rust configuration measures wrapping release arithmetic. Numbers - collected during Osprey's superseded plain-arithmetic experiment are - historical and must be regenerated before supporting current claims. + while this Rust configuration measures wrapping release arithmetic. Every + number on this page was measured under that contract. - **Osprey loops via `range |> fold`,** not deep linear recursion, because it has no tail-call optimization yet (a 1e6-deep recursion overflows the stack). The work is identical; only the iteration mechanism differs. - **OCaml is built without flambda** (stock `ocamlopt`), so its numbers are conservative versus an flambda build. - **Single machine, wall clock.** Treat ratios as indicative; re-run locally with - `make bench`. The exact set of outright wins shifts run-to-run because Osprey, - Rust, and C now sit within measurement noise of one another. + `make bench`. ## Where the gap remains -The checked-arithmetic change invalidates the old attribution of CPU and memory -gaps to `/` and `%` alone. Integer `+ - *` now produce the same explicit Result -shape, so arithmetic-heavy rows include that safety cost too. Re-run -`make bench` before drawing current per-case conclusions from this historical -table. +Osprey is not the fastest language in this table on any case. Averaged across +the suite it runs **11.6× Rust's CPU time and 13.1× C's**, and the default +memory backend never wins a row either — `binarytrees` peaks at **1.77 GB** +against C's 1.75 MB. -**That is a backend choice, not a language one.** Allocation funnels through the -one swappable boundary of the +The CPU gap is not attributable to `/` and `%` alone. Under +[ARITH-CHECKED](/spec/0013-errorhandling/) integer `+ - *` also produce an +explicit `Result`, so every arithmetic-heavy row carries that +safety cost: `fn addup(a, b) = a + b` returns a heap-allocated Result, not an +`i64`. Making that representation cheap is open work; removing its failure +channel is not. + +**The memory gap is a backend choice, not a language one.** Allocation funnels +through the one swappable boundary of the [Memory Management spec](/spec/0018-memorymanagement/), and under -`--memory=arc` (Perceus reference counting) **every case drops to 1.5–3.5 MB** — -matching C throughout, beating it on `exprtree` — with no change to a line of -Osprey source. +`--memory=arc` (Perceus reference counting) **every case drops to 1.5–3.4 MB**, +with no change to a line of Osprey source. That lands ARC within striking +distance of C — a median of **1.06× C's peak RSS**, from 0.30× on `exprtree` +(where it beats C outright) to 1.65× on `binarytrees` — turning a 1000× +memory deficit into a rounding error. Wall clock cuts both ways, and the split is the opposite of what you might expect. On the 17 allocation-light cases ARC is slightly *faster* than the