generic-builder: optimize - reduce execve calls when sourcing

This improves the implementation of `dumpVars` by removing a call to `install`.

This improves performance when sourcing setup.sh by more than 10%
It should also improve the performance when transitioning between build phases significantly as no process executions are issued anymore,

A test is added, which ensures that no extra execve calls are issued while sourcing setup.sh.
This commit is contained in:
DavHau
2025-06-16 11:56:12 +07:00
parent d3d2d80a21
commit 4a42314f72
2 changed files with 56 additions and 8 deletions
+12 -7
View File
@@ -1181,13 +1181,18 @@ substituteAllInPlace() {
# the environment used for building.
dumpVars() {
if [ "${noDumpEnvVars:-0}" != 1 ]; then
# On darwin, install(1) cannot be called with /dev/stdin or fd from process substitution
# so first we create the file and then write to it
# See https://github.com/NixOS/nixpkgs/issues/335016
{
install -m 0600 /dev/null "$NIX_BUILD_TOP/env-vars" &&
export 2>/dev/null >| "$NIX_BUILD_TOP/env-vars"
} || true
# Don't use `install` here to prevent executing a process each time.
# Set umask to create env-vars file with 0600 permissions (owner read/write only)
local old_umask
old_umask=$(umask)
umask 0077
# Dump all environment variables to the env-vars file
export 2>/dev/null > "$NIX_BUILD_TOP/env-vars"
# Restore original umask
umask "$old_umask"
fi
}
+44 -1
View File
@@ -404,6 +404,50 @@ in
stdenv' = bootStdenv;
};
ensure-no-execve-in-setup-sh =
derivation {
name = "ensure-no-execve-in-setup-sh";
system = stdenv.system;
builder = "${stdenv.bootstrapTools}/bin/bash";
PATH = "${pkgs.strace}/bin:${stdenv.bootstrapTools}/bin";
initialPath = [
stdenv.bootstrapTools
pkgs.strace
];
args = [
"-c"
''
countCall() {
echo "$stats" | tr -s ' ' | grep "$1" | cut -d ' ' -f5
}
# prevent setup.sh from running `nproc` when cores=0
# (this would mess up the syscall stats)
export NIX_BUILD_CORES=1
echo "Analyzing setup.sh with strace"
stats=$(strace -fc bash -c ". ${../../stdenv/generic/setup.sh}" 2>&1)
echo "$stats" | head -n15
# fail if execve calls is > 1
stats=$(strace -fc bash -c ". ${../../stdenv/generic/setup.sh}" 2>&1)
execveCalls=$(countCall execve)
if [ "$execveCalls" -gt 1 ]; then
echo "execve calls: $execveCalls; expected: 1"
echo "ERROR: setup.sh should not launch additional processes when being sourced"
exit 1
else
echo "setup.sh doesn't launch extra processes when sourcing, as expected"
fi
touch $out
''
];
}
// {
meta = { };
};
structuredAttrsByDefault = lib.recurseIntoAttrs {
hooks = lib.recurseIntoAttrs (
@@ -570,6 +614,5 @@ in
diff $out/json $goldenJson
'';
};
};
}