anoma / juvix

A language for intent-centric and declarative decentralised applications
https://docs.juvix.org
GNU General Public License v3.0
442 stars 54 forks source link

Optimize `letFunctionDefs` in `Juvix.Compiler.Internal.Data.InfoTable` #2867

Closed lukaszcz closed 2 days ago

lukaszcz commented 2 days ago

Benchmark results

Using Uniplate:

heliax@imac bench % hyperfine --prepare 'juvix clean --global' -w 1 'juvix typecheck bench.juvix -N 1'
Benchmark 1: juvix typecheck bench.juvix -N 1
  Time (mean ± σ):      1.399 s ±  0.023 s    [User: 1.346 s, System: 0.041 s]
  Range (min … max):    1.374 s …  1.452 s    10 runs

Using HasLetDefs:

heliax@imac bench % hyperfine --prepare 'juvix clean --global' -w 1 'juvix typecheck bench.juvix -N 1'
Benchmark 1: juvix typecheck bench.juvix -N 1
  Time (mean ± σ):      1.098 s ±  0.015 s    [User: 1.047 s, System: 0.040 s]
  Range (min … max):    1.074 s …  1.120 s    10 runs

So it's roughly 1.1s vs. 1.4s, faster by 0.2s. About 14% improvement.

The benchmark file just imports the standard library:

module bench;

import Stdlib.Prelude open;

main : Nat := 0;

Both juvix binaries were compiled with optimizations, using just install.

lukaszcz commented 2 days ago

I think the conclusion from this is that we should never use automatically generated Uniplate instances to traverse the whole program tree or anything sizeable. The performance penalty is ridiculous -- we were traversing only twice to get all lets (once before and once after type checking) and this alone took above 14% of total running time.