From c59bac08bd6fe608eac0083a68ec96819a32662d Mon Sep 17 00:00:00 2001 From: Timothy Gallion Date: Sun, 30 Mar 2025 01:52:11 -0400 Subject: [PATCH 1/2] python3: Fixing excessive memory usage for overriden python An attempt to address #338231. The current release of nixpkgs takes over 20GB of memory to evaluate python when the interpreter is overriden. This adds memoization to the spliced python packages to avoid evaluating all the commbinations of overrides. --- .../interpreters/python/cpython/default.nix | 35 ++++++++++++++----- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/pkgs/development/interpreters/python/cpython/default.nix b/pkgs/development/interpreters/python/cpython/default.nix index 977dd577fc90..56c4fe09fdce 100644 --- a/pkgs/development/interpreters/python/cpython/default.nix +++ b/pkgs/development/interpreters/python/cpython/default.nix @@ -55,6 +55,7 @@ pkgsBuildTarget, pkgsHostHost, pkgsTargetTarget, + __splices ? { }, # build customization sourceVersion, @@ -145,10 +146,28 @@ let # When we override the interpreter we also need to override the spliced versions of the interpreter # bluez is excluded manually to break an infinite recursion. inputs' = lib.filterAttrs (n: v: n != "bluez" && n != "passthruFun" && !lib.isDerivation v) inputs; + # Memoization of the splices to avoid re-evaluating this function for all combinations of splices e.g. + # python3.pythonOnBuildForHost.pythonOnBuildForTarget == python3.pythonOnBuildForTarget by consuming + # __splices as an arg and using the cache if populated. + splices = { + pythonOnBuildForBuild = override pkgsBuildBuild.${pythonAttr}; + pythonOnBuildForHost = override pkgsBuildHost.${pythonAttr}; + pythonOnBuildForTarget = override pkgsBuildTarget.${pythonAttr}; + pythonOnHostForHost = override pkgsHostHost.${pythonAttr}; + pythonOnTargetForTarget = lib.optionalAttrs (lib.hasAttr pythonAttr pkgsTargetTarget) ( + override pkgsTargetTarget.${pythonAttr} + ); + } // __splices; override = attr: let - python = attr.override (inputs' // { self = python; }); + python = attr.override ( + inputs' + // { + self = python; + __splices = splices; + } + ); in python; in @@ -160,13 +179,13 @@ let pythonVersion = with sourceVersion; "${major}.${minor}"; sitePackages = "lib/${libPrefix}/site-packages"; inherit hasDistutilsCxxPatch pythonAttr; - pythonOnBuildForBuild = override pkgsBuildBuild.${pythonAttr}; - pythonOnBuildForHost = override pkgsBuildHost.${pythonAttr}; - pythonOnBuildForTarget = override pkgsBuildTarget.${pythonAttr}; - pythonOnHostForHost = override pkgsHostHost.${pythonAttr}; - pythonOnTargetForTarget = lib.optionalAttrs (lib.hasAttr pythonAttr pkgsTargetTarget) ( - override pkgsTargetTarget.${pythonAttr} - ); + inherit (splices) + pythonOnBuildForBuild + pythonOnBuildForHost + pythonOnBuildForTarget + pythonOnHostForHost + pythonOnTargetForTarget + ; }; version = with sourceVersion; "${major}.${minor}.${patch}${suffix}"; From 0ce0b01c126b892d2f334e3c926f46b62cf52c25 Mon Sep 17 00:00:00 2001 From: Timothy Gallion Date: Sun, 30 Mar 2025 16:10:39 -0400 Subject: [PATCH 2/2] python3: Remove unneeded override in `passthruFun` `pythonOnBuildForHost` is already overriden when it is passed to `passthruFun` remove redundant override. Performace is slightly better ~200MB less memory. --- pkgs/development/interpreters/python/passthrufun.nix | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/pkgs/development/interpreters/python/passthrufun.nix b/pkgs/development/interpreters/python/passthrufun.nix index d4e20aa24fc9..be5d8a11add5 100644 --- a/pkgs/development/interpreters/python/passthrufun.nix +++ b/pkgs/development/interpreters/python/passthrufun.nix @@ -106,10 +106,6 @@ let python = self; } ); - pythonOnBuildForHost_overridden = pythonOnBuildForHost.override { - inherit packageOverrides; - self = pythonOnBuildForHost_overridden; - }; in rec { isPy27 = pythonVersion == "2.7"; @@ -144,7 +140,7 @@ rec { pythonAtLeast = lib.versionAtLeast pythonVersion; pythonOlder = lib.versionOlder pythonVersion; inherit hasDistutilsCxxPatch; - pythonOnBuildForHost = pythonOnBuildForHost_overridden; + inherit pythonOnBuildForHost; tests = callPackage ./tests.nix { python = self;