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.
# e.g. each item is an ordinary attrset or primitive.
# 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
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.
# 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,
# 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.
wipePath = acc: path: lib.recursiveUpdate acc (lib.setAttrByPath path null);
remainder = builtins.foldl' wipePath i paths;
expected-remainder = builtins.foldl' wipePath {} paths;
remainder = builtins.foldl' _wipePath i paths;
expected-remainder = builtins.foldl' _wipePath {} paths;
in
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.:
# <top>.byStore.private = [ ".cache/vim" ];
# <top>.byStore.private = [ { path=".cache/vim"; mode = "0700"; } ];
@@ -140,29 +153,12 @@ let
'';
};
};
config = 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"];
};
# 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 {
config = {
byPath = lib.mkMerge (concatLists [
# 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
(applyToAllStores annotateWithStore)
(applyToAllStores config.byStore annotateWithStore)
]);
};
});

View File

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

View File

@@ -1,20 +1,4 @@
{ lib }:
{
method,
allowedPaths ? [],
allowedHomePaths ? [],
allowedRunPaths ? [],
autodetectCliPaths ? false,
capabilities ? [],
dns ? null,
keepIpc ? false,
keepPids ? false,
tryKeepUsers ? false,
netDev ? null,
netGateway ? null,
whitelistPwd ? false,
extraConfig ? [],
}:
let
saneboxGenerators = {
autodetectCliPaths = style: [ "--sanebox-autodetect" style ];
@@ -26,9 +10,9 @@ let
method = method: [ "--sanebox-method" method ];
netDev = netDev: [ "--sanebox-net-dev" netDev ];
netGateway = netGateway: [ "--sanebox-net-gateway" netGateway ];
path = p: [ "--sanebox-path" p ];
path-home = p: [ "--sanebox-home-path" p ];
path-run = p: [ "--sanebox-run-path" p ];
path.unqualified = p: [ "--sanebox-path" p ];
path.home = p: [ "--sanebox-home-path" p ];
path.run = p: [ "--sanebox-run-path" p ];
whitelistPwd = [ "--sanebox-add-pwd" ];
};
bunpenGenerators = {
@@ -61,32 +45,50 @@ let
else
[ "--bunpen-path" "/dev/net/tun" "--bunpen-net-dev" n ];
netGateway = netGateway: [ "--bunpen-net-gateway" netGateway ];
path = p: [ "--bunpen-path" p ];
path-home = p: [ "--bunpen-home-path" p ];
path-run = p: [ "--bunpen-run-path" p ];
path.unqualified = p: [ "--bunpen-path" p ];
path.home = p: [ "--bunpen-home-path" p ];
path.run = p: [ "--bunpen-run-path" p ];
tryKeepUsers = [ "--bunpen-try-keep-users" ];
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
bunpenGenerators
else
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);
netItems = lib.optionals (netDev != null) (gen.netDev netDev)
++ lib.optionals (netGateway != null) (gen.netGateway netGateway)
++ lib.optionals (dns != null) (lib.flatten (builtins.map gen.dns dns))
++ lib.optionals (netGateway != null) (gen.netGateway netGateway)
++ lib.optionals (dns != null) (lib.flatten (builtins.map gen.dns dns))
;
in
(gen.method method)
++ netItems
++ allowPaths "" allowedPaths
++ allowPaths "-home" allowedHomePaths
++ allowPaths "-run" allowedRunPaths
++ allowPaths "unqualified" allowedPaths
++ allowPaths "home" allowedHomePaths
++ allowPaths "run" allowedRunPaths
++ capabilityFlags
++ lib.optionals (autodetectCliPaths != null) (gen.autodetectCliPaths autodetectCliPaths)
++ 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.
# for example, `pkgs` *must* be added before `cross`, as the latter applies overrides
# to the packages defined in the former.
final: prev:
let
pkgs = import ./pkgs.nix;
preferences = import ./preferences.nix;
cross = import ./cross.nix;
pkgs-ccache = import ./pkgs-ccache.nix;
pkgs-debug = import ./pkgs-debug.nix;
in
final: prev:
let
isCross = prev.stdenv.hostPlatform != prev.stdenv.buildPlatform;
ifCross = overlay: if isCross then overlay else (_: _: {});