docs(tvix/eval): start a document on known optimisation potential
Change-Id: I9bc41e57e1cfdf536d7b9048bac2e7aff1ee2ffa Reviewed-on: https://cl.tvl.fyi/c/depot/+/6313 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
This commit is contained in:
parent
3089e46eb1
commit
06b07f5c47
1 changed files with 57 additions and 0 deletions
57
tvix/eval/docs/known-optimisation-potential.md
Normal file
57
tvix/eval/docs/known-optimisation-potential.md
Normal file
|
@ -0,0 +1,57 @@
|
|||
Known Optimisation Potential
|
||||
============================
|
||||
|
||||
There are several areas of the Tvix evaluator code base where
|
||||
potentially large performance gains can be achieved through
|
||||
optimisations that we are already aware of.
|
||||
|
||||
The shape of most optimisations is that of moving more work into the
|
||||
compiler to simplify the runtime execution of Nix code. This leads, in
|
||||
some cases, to drastically higher complexity in both the compiler
|
||||
itself and in invariants that need to be guaranteed between the
|
||||
runtime and the compiler.
|
||||
|
||||
For this reason, and because we lack the infrastructure to adequately
|
||||
track their impact (WIP), we have not yet implemented these
|
||||
optimisations, but note the most important ones here.
|
||||
|
||||
* Use "open upvalues" [hard]
|
||||
|
||||
Right now, Tvix will immediately close over all upvalues that are
|
||||
created and clone them into the `Closure::upvalues` array.
|
||||
|
||||
Instead of doing this, we can statically determine most locals that
|
||||
are closed over *and escape their scope* (similar to how the
|
||||
`compiler::scope::Scope` struct currently tracks whether locals are
|
||||
used at all).
|
||||
|
||||
If we implement the machinery to track this, we can implement some
|
||||
upvalues at runtime by simply sticking stack indices in the upvalue
|
||||
array and only copy the values where we know that they escape.
|
||||
|
||||
* Avoid `with` value duplication [easy]
|
||||
|
||||
If a `with` makes use of a local identifier in a scope that can not
|
||||
close before the with (e.g. not across `LambdaCtx` boundaries), we
|
||||
can avoid the allocation of the phantom value and duplication of the
|
||||
`NixAttrs` value on the stack. In this case we simply push the stack
|
||||
index of the known local.
|
||||
|
||||
* Multiple attribute selection [medium]
|
||||
|
||||
An instruction could be introduced that avoids repeatedly pushing an
|
||||
attribute set to/from the stack if multiple keys are being selected
|
||||
from it. This occurs, for example, when inheriting from an attribute
|
||||
set or when binding function formals.
|
||||
|
||||
* Split closure/function representation [easy]
|
||||
|
||||
Functions have fewer fields that need to be populated at runtime and
|
||||
can directly use the `value::function::Lambda` representation where
|
||||
possible.
|
||||
|
||||
* Tail-call optimisation [hard]
|
||||
|
||||
We can statically detect the conditions for tail-call optimisation.
|
||||
The compiler should do this, and it should then emit a new operation
|
||||
for doing the tail-calls.
|
Loading…
Reference in a new issue