This PR adds a clone of the `mvcgen` tactic based on `SymM` and evaluates it based on a ported `add_sub_cancel` benchmark. Notably, it can reuse all the existing `@[spec]`-annotated theorems to generate VCs. (It doesn't do control-flow splitting, simp rules on the program expression or handling of lets; we'll get there.) It is quite fast already, with the kernel being the bottle-neck: ``` goal_50: 69.524305 ms, kernel: 155.327778 ms goal_100: 93.834221 ms, kernel: 407.370786 ms goal_150: 131.364098 ms, kernel: 762.936720 ms goal_200: 169.577172 ms, kernel: 1181.199093 ms goal_250: 206.421738 ms, kernel: 1707.539380 ms ``` ``` goal_200: 169.458637 ms, kernel: 1186.221085 ms goal_400: 322.819718 ms, kernel: 3791.613854 ms goal_600: 474.929013 ms, kernel: 7763.373757 ms goal_800: 634.379422 ms, kernel: 13107.810430 ms ``` It is best compared to the `solveUsingSym <n> false true` measurements of the SymM `add_sub_cancel` benchmark (`false`: without intermediate eager simplification). For `n=200`, it reports ``` goal_200: 779.482300 ms, kernel: 742.097404 ms ``` suggesting that the generated proof term could be improved for kernel reduction. (TODO.) I'm unsure whether `solveUsingSym` is run in interpreted mode, so take the >400% speedup with a grain of salt. We can definitely conclude that VC generation time is currently not a bottleneck compared to kernel checking time. Plot for discharging goals of sizes 100..800: <img width="1000" height="600" alt="Code_Generated_Image(1)" src="https://github.com/user-attachments/assets/90e76a45-fa46-4d02-912a-c3355e2aa094" /> Plot comparing Kernel and Goal time: <img width="1000" height="600" alt="Code_Generated_Image(2)" src="https://github.com/user-attachments/assets/5849ba0f-1d83-4f2d-98dd-fa65b840bb4e" /> |
||
|---|---|---|
| .. | ||
| inundation | ||
| mergeSort | ||
| mvcgen | ||
| qsort | ||
| sym | ||
| .gitignore | ||
| accumulate_profile.py | ||
| arith_eval.ml | ||
| big_beq.lean | ||
| big_beq_rec.lean | ||
| big_deceq.lean | ||
| big_deceq_rec.lean | ||
| big_do.lean | ||
| big_match.lean | ||
| big_match_nat.lean | ||
| big_match_nat_split.lean | ||
| big_match_partial.lean | ||
| big_omega.lean | ||
| big_struct.lean | ||
| big_struct_dep.lean | ||
| big_struct_dep1.lean | ||
| binarytrees.ghc-6.hs | ||
| binarytrees.lean | ||
| binarytrees.lean.args | ||
| binarytrees.lean.expected.out | ||
| binarytrees.ocaml-2.ml | ||
| binarytrees.st.hs | ||
| binarytrees.st.lean | ||
| binarytrees.st.mlton-2.sml | ||
| binarytrees.st.sml | ||
| binarytrees.st.swift | ||
| binarytrees.swift | ||
| binarytrees5.ml | ||
| binarytrees5_multicore.ml | ||
| bv_decide_inequality.lean | ||
| bv_decide_large_aig.lean | ||
| bv_decide_mod.lean | ||
| bv_decide_mul.lean | ||
| bv_decide_realworld.lean | ||
| bv_decide_rewriter.lean | ||
| channel.lean | ||
| charactersIn.lean | ||
| compile.sh | ||
| const_fold.hs | ||
| const_fold.lean | ||
| const_fold.lean.args | ||
| const_fold.lean.expected.out | ||
| const_fold.ml | ||
| const_fold.sml | ||
| const_fold.swift | ||
| cross.yaml | ||
| dag_hassorry_issue.lean | ||
| dag_hassorry_issue.lean.args | ||
| dag_hassorry_issue.lean.expected.out | ||
| delayed_assign.lean | ||
| deriv.hs | ||
| deriv.lean | ||
| deriv.lean.args | ||
| deriv.lean.expected.out | ||
| deriv.ml | ||
| deriv.sml | ||
| deriv.swift | ||
| ex-50-50-1.leq | ||
| flake.lock | ||
| flake.nix | ||
| full-stdlib.exec.yaml | ||
| ghc-gc.py | ||
| hashmap.lean | ||
| identifier_completion.lean | ||
| identifier_completion_didOpen.log | ||
| identifier_completion_initialization.log | ||
| identifier_completion_runner.lean | ||
| ilean_roundtrip.lean | ||
| iterators.lean | ||
| lean-gc.py | ||
| liasolver.lean | ||
| liasolver.lean.args | ||
| liasolver.lean.expected.out | ||
| Makefile | ||
| mlkit-gc.py | ||
| mut_rec_wf.lean | ||
| nat_repr.lean | ||
| nat_repr.lean.args | ||
| nat_repr.lean.expected.out | ||
| ocaml-gc.py | ||
| omega_stress.lean | ||
| parser.lean | ||
| perf.py | ||
| phashmap.lean | ||
| qsort.hs | ||
| qsort.lean | ||
| qsort.lean.args | ||
| qsort.lean.expected.out | ||
| qsort.ml | ||
| qsort.sml | ||
| qsort.swift | ||
| rbmap.hs | ||
| rbmap.lean | ||
| rbmap.lean.args | ||
| rbmap.lean.expected.out | ||
| rbmap.ml | ||
| rbmap.sml | ||
| rbmap.swift | ||
| rbmap2.lean | ||
| rbmap3.lean | ||
| rbmap500k.lean | ||
| rbmap_checkpoint.hs | ||
| rbmap_checkpoint.lean | ||
| rbmap_checkpoint.lean.args | ||
| rbmap_checkpoint.lean.expected.out | ||
| rbmap_checkpoint.ml | ||
| rbmap_checkpoint.sml | ||
| rbmap_checkpoint.swift | ||
| rbmap_checkpoint2.lean | ||
| rbmap_checkpoint2.sml | ||
| rbmap_checkpoint_cpp_lean3.cpp | ||
| rbmap_checkpoint_cpp_std.cpp | ||
| rbmap_cpp_lean3.cpp | ||
| rbmap_cpp_std.cpp | ||
| rbmap_fbip.lean | ||
| rbmap_library.lean | ||
| README.md | ||
| reduceMatch.lean | ||
| report.py | ||
| riscv-ast.lean | ||
| run.sh | ||
| server_startup.lean | ||
| server_startup.log | ||
| sigmaIterator.lean | ||
| simp_arith1.lean | ||
| simp_bubblesort_256.lean | ||
| simp_congr.lean | ||
| simp_local.lean | ||
| simp_subexpr.lean | ||
| speedcenter.exec.velcom.yaml | ||
| speedcenter.yaml | ||
| states35.lean | ||
| test_single.sh | ||
| treemap.lean | ||
| unionfind.lean | ||
| unionfind.lean.args | ||
| unionfind.lean.expected.out | ||
| unionfind_clean.lean | ||
| watchdogRss.lean | ||
| workspaceSymbols.lean | ||
| workspaceSymbolsNewRanges.lean | ||
Lean Benchmark Suites
This folder contains multiple small Lean programs for benchmarking used by two separate benchmark suites based on the temci benchmarking tool:
- The light-weight "Speedcenter" suite benchmarks the current build of Lean. It can be used for quick comparisons on the cmdline and powers the Lean Speedcenter website.
- The heavy-weight "Cross" suite benchmarks multiple Lean configurations and other functional compilers against each other and generates CSV and HTML reports from that. It was created for the paper "Counting Immutable Beans - Reference Counting Optimized for Purely Functional Programming" (IFL19).
Speedcenter Suite
Requirements:
- A local Lean build in
../../build/release. Build at least thebintarget. - temci. Using Nix, open a nix-shell in the project
root directory to add a compatible version to your PATH. Alternatively, try
pip3 install git+https://github.com/parttimenerd/temci.git.
To execute the suite and save the results in base.yaml, run (in this folder)
temci exec --config speedcenter.yaml --out base.yaml
Other interesting exec flags:
- use
--runs Nto modify the default number of 10 runs per benchmark - use
--included_blocks fastto excluded slow benchmarks like the stdlib benchmark. You can replacefastwith any benchmark name or label inspeedcenter.exec.yaml.
If you have multiple saved result files, you can compare them with
temci report --config speedcenter.yaml report1.yaml report2.yaml ...
Cross Suite
We recommend using Nix for building/obtaining all Lean variants and used compilers in a reproducible way. After installing Nix, running the benchmarks is as easy as
nix develop
make
This will record 50 runs for each benchmark configuration (this can be changed with runs in cross.yaml),
generate results in report_lean.csv and report_cross.csv, and print them to stdout in a tabulated format.
It will also generate HTML reports in report/ comparing the time-based benchmarks.
In order to reduce noise in the benchmarking data, you may instead want to try calling make inside a
temci shell:
temci short shell --sudo --preset usable --cpuset_active make
Using root powers, this will temporarily configure your machine similarly to the LLVM benchmarking recommendations and move all your other processes to a single CPU core.