refactor: optimize eval time

lifting `let` bindings up where possible helps reduce the number of thunks nix has to allocate. this patch only does that by 0.3%-ish, though
This commit is contained in:
2024-10-01 03:54:44 +00:00
parent 80c67caf19
commit 61df81291b
5 changed files with 62 additions and 63 deletions

View File

@@ -62,14 +62,13 @@ rec {
# now items is a list where every element is undecorated at the toplevel. # now items is a list where every element is undecorated at the toplevel.
# e.g. each item is an ordinary attrset or primitive. # e.g. each item is an ordinary attrset or primitive.
# we still need to discharge the *rest* of the path though, for every item. # we still need to discharge the *rest* of the path though, for every item.
name = lib.head path;
downstream = lib.tail path;
dischargeDownstream = it: if path != [] && it ? name then
builtins.map (v: it // { "${name}" = v; }) (dischargeToPath downstream it."${name}")
else
[ it ];
in in
lib.concatMap dischargeDownstream items; lib.concatMap (dischargeDownstream path) items;
dischargeDownstream = path: it: if path != [] && it ? name then
builtins.map (v: it // { "${lib.head path}" = v; }) (dischargeToPath (lib.tail path) it."${lib.head path}")
else
[ it ];
# discharge many items but only over one path. # discharge many items but only over one path.
# Type: dischargeItemsToPaths :: [Attrs] -> String -> [Attrs] # Type: dischargeItemsToPaths :: [Attrs] -> String -> [Attrs]
@@ -92,9 +91,10 @@ rec {
# since the act of discharging should have forced all the relevant data out to the leaves, # since the act of discharging should have forced all the relevant data out to the leaves,
# we just set each expected terminal to null (initializing the parents when necessary) # we just set each expected terminal to null (initializing the parents when necessary)
# and that gives a standard value for any fully-consumed items that we can do equality comparisons with. # and that gives a standard value for any fully-consumed items that we can do equality comparisons with.
wipePath = acc: path: lib.recursiveUpdate acc (lib.setAttrByPath path null); remainder = builtins.foldl' _wipePath i paths;
remainder = builtins.foldl' wipePath i paths; expected-remainder = builtins.foldl' _wipePath {} paths;
expected-remainder = builtins.foldl' wipePath {} paths;
in in
assert remainder == expected-remainder; true; assert remainder == expected-remainder; true;
_wipePath = acc: path: lib.recursiveUpdate acc (lib.setAttrByPath path null);
} }

View File

@@ -118,6 +118,19 @@ let
} }
]; ];
# set the `store` attribute on one dir attrset
annotateWithStore = store: dir: {
"${dir.path}".store = store;
};
# convert an `entryInStore` to an `entryAtPath` (less the `store` item)
dirToAttrs = dir: {
"${dir.path}" = builtins.removeAttrs dir ["path"];
};
# AttrSet -> (store -> path -> AttrSet) -> [AttrSet]
applyToAllStores = byStore: f: lib.concatMap
(store: map (f store) byStore."${store}")
(builtins.attrNames byStore);
# this submodule converts store-based access to path-based access so that the user can specify e.g.: # this submodule converts store-based access to path-based access so that the user can specify e.g.:
# <top>.byStore.private = [ ".cache/vim" ]; # <top>.byStore.private = [ ".cache/vim" ];
# <top>.byStore.private = [ { path=".cache/vim"; mode = "0700"; } ]; # <top>.byStore.private = [ { path=".cache/vim"; mode = "0700"; } ];
@@ -140,29 +153,12 @@ let
''; '';
}; };
}; };
config = let config = {
# set the `store` attribute on one dir attrset
annotateWithStore = store: dir: {
"${dir.path}".store = store;
};
# convert an `entryInStore` to an `entryAtPath` (less the `store` item)
dirToAttrs = dir: {
"${dir.path}" = builtins.removeAttrs dir ["path"];
};
# store-names = attrNames cfg.stores;
# :: (store -> entry -> AttrSet) -> [AttrSet]
# applyToAllStores = f: lib.concatMap
# (store: map (f store) config.byStore."${store}")
# store-names;
applyToAllStores = f: lib.concatMap
(store: map (f store) config.byStore."${store}")
(builtins.attrNames config.byStore);
in {
byPath = lib.mkMerge (concatLists [ byPath = lib.mkMerge (concatLists [
# convert the list-style per-store entries into attrsOf entries # convert the list-style per-store entries into attrsOf entries
(applyToAllStores (_store: dirToAttrs)) (applyToAllStores config.byStore (_store: dirToAttrs))
# add the `store` attr to everything we ingested # add the `store` attr to everything we ingested
(applyToAllStores annotateWithStore) (applyToAllStores config.byStore annotateWithStore)
]); ]);
}; };
}); });

View File

@@ -3,6 +3,9 @@ let
saneCfg = config.sane; saneCfg = config.sane;
cfg = config.sane.programs; cfg = config.sane.programs;
makeSandboxArgs = pkgs.callPackage ./make-sandbox-args.nix { };
makeSandboxed = pkgs.callPackage ./make-sandboxed.nix { };
# create a map: # create a map:
# { # {
# "${pkgName}" = { # "${pkgName}" = {
@@ -38,9 +41,6 @@ let
package package
else else
let let
makeSandboxArgs = pkgs.callPackage ./make-sandbox-args.nix { };
makeSandboxed = pkgs.callPackage ./make-sandboxed.nix { };
vpn = if sandbox.net == "vpn" then vpn = if sandbox.net == "vpn" then
lib.findSingle (v: v.isDefault) null null (builtins.attrValues config.sane.vpn) lib.findSingle (v: v.isDefault) null null (builtins.attrValues config.sane.vpn)
else if sandbox.net == "vpn.wg-home" then else if sandbox.net == "vpn.wg-home" then

View File

@@ -1,20 +1,4 @@
{ lib }: { lib }:
{
method,
allowedPaths ? [],
allowedHomePaths ? [],
allowedRunPaths ? [],
autodetectCliPaths ? false,
capabilities ? [],
dns ? null,
keepIpc ? false,
keepPids ? false,
tryKeepUsers ? false,
netDev ? null,
netGateway ? null,
whitelistPwd ? false,
extraConfig ? [],
}:
let let
saneboxGenerators = { saneboxGenerators = {
autodetectCliPaths = style: [ "--sanebox-autodetect" style ]; autodetectCliPaths = style: [ "--sanebox-autodetect" style ];
@@ -26,9 +10,9 @@ let
method = method: [ "--sanebox-method" method ]; method = method: [ "--sanebox-method" method ];
netDev = netDev: [ "--sanebox-net-dev" netDev ]; netDev = netDev: [ "--sanebox-net-dev" netDev ];
netGateway = netGateway: [ "--sanebox-net-gateway" netGateway ]; netGateway = netGateway: [ "--sanebox-net-gateway" netGateway ];
path = p: [ "--sanebox-path" p ]; path.unqualified = p: [ "--sanebox-path" p ];
path-home = p: [ "--sanebox-home-path" p ]; path.home = p: [ "--sanebox-home-path" p ];
path-run = p: [ "--sanebox-run-path" p ]; path.run = p: [ "--sanebox-run-path" p ];
whitelistPwd = [ "--sanebox-add-pwd" ]; whitelistPwd = [ "--sanebox-add-pwd" ];
}; };
bunpenGenerators = { bunpenGenerators = {
@@ -61,32 +45,50 @@ let
else else
[ "--bunpen-path" "/dev/net/tun" "--bunpen-net-dev" n ]; [ "--bunpen-path" "/dev/net/tun" "--bunpen-net-dev" n ];
netGateway = netGateway: [ "--bunpen-net-gateway" netGateway ]; netGateway = netGateway: [ "--bunpen-net-gateway" netGateway ];
path = p: [ "--bunpen-path" p ]; path.unqualified = p: [ "--bunpen-path" p ];
path-home = p: [ "--bunpen-home-path" p ]; path.home = p: [ "--bunpen-home-path" p ];
path-run = p: [ "--bunpen-run-path" p ]; path.run = p: [ "--bunpen-run-path" p ];
tryKeepUsers = [ "--bunpen-try-keep-users" ]; tryKeepUsers = [ "--bunpen-try-keep-users" ];
whitelistPwd = [ "--bunpen-path" "." ]; whitelistPwd = [ "--bunpen-path" "." ];
}; };
in
{
method,
allowedPaths ? [],
allowedHomePaths ? [],
allowedRunPaths ? [],
autodetectCliPaths ? false,
capabilities ? [],
dns ? null,
keepIpc ? false,
keepPids ? false,
tryKeepUsers ? false,
netDev ? null,
netGateway ? null,
whitelistPwd ? false,
extraConfig ? [],
}:
let
gen = if method == "bunpen" then gen = if method == "bunpen" then
bunpenGenerators bunpenGenerators
else else
saneboxGenerators saneboxGenerators
; ;
allowPaths = flavor: paths: lib.flatten (builtins.map gen."path${flavor}" paths); allowPaths = flavor: paths: lib.flatten (builtins.map gen.path."${flavor}" paths);
capabilityFlags = lib.flatten (builtins.map gen.capability capabilities); capabilityFlags = lib.flatten (builtins.map gen.capability capabilities);
netItems = lib.optionals (netDev != null) (gen.netDev netDev) netItems = lib.optionals (netDev != null) (gen.netDev netDev)
++ lib.optionals (netGateway != null) (gen.netGateway netGateway) ++ lib.optionals (netGateway != null) (gen.netGateway netGateway)
++ lib.optionals (dns != null) (lib.flatten (builtins.map gen.dns dns)) ++ lib.optionals (dns != null) (lib.flatten (builtins.map gen.dns dns))
; ;
in in
(gen.method method) (gen.method method)
++ netItems ++ netItems
++ allowPaths "" allowedPaths ++ allowPaths "unqualified" allowedPaths
++ allowPaths "-home" allowedHomePaths ++ allowPaths "home" allowedHomePaths
++ allowPaths "-run" allowedRunPaths ++ allowPaths "run" allowedRunPaths
++ capabilityFlags ++ capabilityFlags
++ lib.optionals (autodetectCliPaths != null) (gen.autodetectCliPaths autodetectCliPaths) ++ lib.optionals (autodetectCliPaths != null) (gen.autodetectCliPaths autodetectCliPaths)
++ lib.optionals keepIpc gen.keepIpc ++ lib.optionals keepIpc gen.keepIpc

View File

@@ -1,14 +1,15 @@
# this overlay exists specifically to control the order in which other overlays are applied. # this overlay exists specifically to control the order in which other overlays are applied.
# for example, `pkgs` *must* be added before `cross`, as the latter applies overrides # for example, `pkgs` *must* be added before `cross`, as the latter applies overrides
# to the packages defined in the former. # to the packages defined in the former.
final: prev:
let let
pkgs = import ./pkgs.nix; pkgs = import ./pkgs.nix;
preferences = import ./preferences.nix; preferences = import ./preferences.nix;
cross = import ./cross.nix; cross = import ./cross.nix;
pkgs-ccache = import ./pkgs-ccache.nix; pkgs-ccache = import ./pkgs-ccache.nix;
pkgs-debug = import ./pkgs-debug.nix; pkgs-debug = import ./pkgs-debug.nix;
in
final: prev:
let
isCross = prev.stdenv.hostPlatform != prev.stdenv.buildPlatform; isCross = prev.stdenv.hostPlatform != prev.stdenv.buildPlatform;
ifCross = overlay: if isCross then overlay else (_: _: {}); ifCross = overlay: if isCross then overlay else (_: _: {});