primops: feat listToAttrsNull#16089
Conversation
listToAttrsNull
|
Where would this be useful? I've never seen this being done in nixpkgs, and I don't expect |
|
This pattern is sometimes used in
About performances, |
But usage without a handful of packages might not really be performance sensitive though. Is this pattern used somewhere in commonly used code throughout nixpkgs (in lib eg.). Ideally of course we'd make nix smart enough to do such matters matching optimisations without making a new primop each time someone finds a new pattern. But that of course relies on the grim future of making nix do non-trivial transformations on the interpreted code, so I'll shut up. |
|
I've ran a clanker to benchmark and find more use cases potentially:
Benchmarking
Benchmark commands: # Current (groupBy)
nix eval --impure --expr '
let
uniqueStrings = list: builtins.attrNames (builtins.groupBy (x: x) list);
names = map (x: "attr-" + toString (x / 2)) (builtins.genList (x: x) 50000);
in
builtins.seq (uniqueStrings names) 42
'
# With listToAttrsNull
nix eval --impure --expr '
let
uniqueStrings = list: builtins.attrNames (builtins.listToAttrsNull list);
names = map (x: "attr-" + toString (x / 2)) (builtins.genList (x: x) 50000);
in
builtins.seq (uniqueStrings names) 42
'While interpreter-level pattern-matching optimization would be ideal in theory, Nix's simple design makes targeted primops (much like |
|
This doesn't feel like the right solution for the three examples
It's a constant attrset, so may as well use an attrset literal.
This would benefit more from Otherwise, we might also consider a primop These two functions can represent a significant portion of whole-attrset consumption in practice, eliminating large intermediate list or attrset allocations when the processing can be moved into the callback.
Needs |
|
Well you are right that it doesn't need to default to null anyway, what matters is that the val is static I've generalized the implementation to builtins.listToAttrsWithValue value listWhich also would benefits in two of the examples I provided earlier
vscode-utils would be okay with a static attrset because even the keys are constant, but otherwise |
As someone who recently cleaned up concatMapAttrs in nixpkgs to not be ridiculously slow, this would definitely be nice. Curious as to the benefit it would make over the new definition, though, since it doesn't use |
Motivation
Constructing an attribute set from a list of strings (where all values are
null) is a common pattern in Nix to represent sets for fast membership checks. This PR introduces a new primopbuiltins.listToAttrsNullto optimize this conversion.Initially, this primop was implemented as
listToSet. However, since Nix does not have a native "Set" type (using attribute sets withnullvalues as a convention), the namelistToSetis misleading. Renaming it tolistToAttrsNullmakes the return type and value behavior explicit, remaining consistent withlistToAttrs.Context
This PR contains:
builtins.listToAttrsNull(originallylistToSet).primops.cc.listToAttrsNulland corresponding unit tests insrc/libexpr-tests/primops.cc.Add 👍 to pull requests you find important.
The Nix maintainer team uses a GitHub project board to schedule and track reviews.