From 4b4d4138177fd467cd8e726470824afac6ad3df5 Mon Sep 17 00:00:00 2001 From: adisbladis Date: Sat, 25 Nov 2023 01:58:52 +1300 Subject: [PATCH] lib.meta: Avoid attrset allocation in platformMatch Benchmarks (`nix-instantiate ./. -A python3`) - Before ``` json { "cpuTime": 0.30625399947166443, "envs": { "bytes": 4484216, "elements": 221443, "number": 169542 }, "gc": { "heapSize": 402915328, "totalBytes": 53091024 }, "list": { "bytes": 749424, "concats": 4242, "elements": 93678 }, "nrAvoided": 253991, "nrFunctionCalls": 149848, "nrLookups": 49614, "nrOpUpdateValuesCopied": 1588326, "nrOpUpdates": 10106, "nrPrimOpCalls": 130356, "nrThunks": 359013, "sets": { "bytes": 30432320, "elements": 1860540, "number": 41480 }, "sizes": { "Attr": 16, "Bindings": 16, "Env": 16, "Value": 24 }, "symbols": { "bytes": 236218, "number": 24459 }, "values": { "bytes": 10504632, "number": 437693 } } ``` - After ``` { "cpuTime": 0.29695799946784973, "envs": { "bytes": 3296712, "elements": 169055, "number": 121517 }, "gc": { "heapSize": 402915328, "totalBytes": 49044992 }, "list": { "bytes": 504928, "concats": 4242, "elements": 63116 }, "nrAvoided": 175403, "nrFunctionCalls": 110554, "nrLookups": 44907, "nrOpUpdateValuesCopied": 1588326, "nrOpUpdates": 10106, "nrPrimOpCalls": 82330, "nrThunks": 306625, "sets": { "bytes": 29943328, "elements": 1843076, "number": 28382 }, "sizes": { "Attr": 16, "Bindings": 16, "Env": 16, "Value": 24 }, "symbols": { "bytes": 236218, "number": 24459 }, "values": { "bytes": 9037752, "number": 376573 } } ``` --- lib/meta.nix | 32 ++++++++++++++++++++++---------- lib/tests/misc.nix | 20 ++++++++++++++++++++ 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/lib/meta.nix b/lib/meta.nix index 2e817c42327d..1a43016d27c4 100644 --- a/lib/meta.nix +++ b/lib/meta.nix @@ -3,6 +3,11 @@ { lib }: +let + inherit (lib) matchAttrs any all; + inherit (builtins) isString; + +in rec { @@ -83,14 +88,21 @@ rec { We can inject these into a pattern for the whole of a structured platform, and then match that. */ - platformMatch = platform: elem: let - pattern = - if builtins.isString elem - then { system = elem; } - else if elem?parsed - then elem - else { parsed = elem; }; - in lib.matchAttrs pattern platform; + platformMatch = platform: elem: ( + # Check with simple string comparison if elem was a string. + # + # The majority of comparisons done with this function will be against meta.platforms + # which contains a simple platform string. + # + # Avoiding an attrset allocation results in significant performance gains (~2-30) across the board in OfBorg + # because this is a hot path for nixpkgs. + if isString elem then platform ? system && elem == platform.system + else matchAttrs ( + # Normalize platform attrset. + if elem ? parsed then elem + else { parsed = elem; } + ) platform + ); /* Check if a package is available on a given platform. @@ -102,8 +114,8 @@ rec { 2. None of `meta.badPlatforms` pattern matches the given platform. */ availableOn = platform: pkg: - ((!pkg?meta.platforms) || lib.any (platformMatch platform) pkg.meta.platforms) && - lib.all (elem: !platformMatch platform elem) (pkg.meta.badPlatforms or []); + ((!pkg?meta.platforms) || any (platformMatch platform) pkg.meta.platforms) && + all (elem: !platformMatch platform elem) (pkg.meta.badPlatforms or []); /* Get the corresponding attribute in lib.licenses from the SPDX ID. diff --git a/lib/tests/misc.nix b/lib/tests/misc.nix index 06cb5e763e2c..8f4a37149d92 100644 --- a/lib/tests/misc.nix +++ b/lib/tests/misc.nix @@ -1948,4 +1948,24 @@ runTests { testGetExe'FailureSecondArg = testingThrow ( getExe' { type = "derivation"; } "dir/executable" ); + + testPlatformMatch = { + expr = meta.platformMatch { system = "x86_64-linux"; } "x86_64-linux"; + expected = true; + }; + + testPlatformMatchAttrs = { + expr = meta.platformMatch (systems.elaborate "x86_64-linux") (systems.elaborate "x86_64-linux").parsed; + expected = true; + }; + + testPlatformMatchNoMatch = { + expr = meta.platformMatch { system = "x86_64-darwin"; } "x86_64-linux"; + expected = false; + }; + + testPlatformMatchMissingSystem = { + expr = meta.platformMatch { } "x86_64-linux"; + expected = false; + }; }