refactor(tvix/eval): use im::Vector for NixList representation

This is a persistent, structurally sharing data structure which is
more efficient in some of our use-cases. I have verified the
efficiency improvement using `hyperfine` repeatedly over expressions
on nixpkgs.

Lists are not the most performance-critical structure in Nix (that
would be attribute sets), but we can already see a small (~5-10%)
improvement.

Note that there are a handful of cases where we still go via `Vec`
that need to be fixed, most notable for `builtins.sort` which can not
currently be implemented directly using `im::Vector` because of a
restrictive type bound.

Change-Id: I237cc50cbd7629a046e5a5e4601fbb40355e551d
Reviewed-on: https://cl.tvl.fyi/c/depot/+/7670
Tested-by: BuildkiteCI
Reviewed-by: sterni <sternenseemann@systemli.org>
This commit is contained in:
Vincent Ambo 2022-12-29 14:44:09 +03:00 committed by tazjin
parent 6ab8320f07
commit 5d73c06b1a
8 changed files with 261 additions and 46 deletions

View file

@ -815,10 +815,9 @@ impl<'o> VM<'o> {
}
OpCode::OpConcat => {
let rhs = fallible!(self, self.pop().to_list());
let mut lhs = fallible!(self, self.pop().to_list()).into_vec();
lhs.extend_from_slice(&rhs);
self.push(Value::List(NixList::from(lhs)))
let rhs = fallible!(self, self.pop().to_list()).into_inner();
let lhs = fallible!(self, self.pop().to_list()).into_inner();
self.push(Value::List(NixList::from(lhs + rhs)))
}
OpCode::OpInterpolate(Count(count)) => self.run_interpolate(count)?,