about summary refs log tree commit diff
path: root/lib
diff options
context:
space:
mode:
authorSilvan Mosberger <contact@infinisil.com>2023-11-26 23:28:39 +0100
committerGitHub <noreply@github.com>2023-11-26 23:28:39 +0100
commit627af21e87ce5d6a456f485292ac4ac2bc1f469f (patch)
tree33ada414becfcdea9f0526ffc1551cec4a665484 /lib
parent64b86e474114f7c6135fbb58fd4753595a0b1510 (diff)
parent4b4d4138177fd467cd8e726470824afac6ad3df5 (diff)
Merge pull request #269637 from adisbladis/lib-meta-avoid-alloc-platformmatch
lib.meta: Avoid attrset allocation in platformMatch
Diffstat (limited to 'lib')
-rw-r--r--lib/meta.nix32
-rw-r--r--lib/tests/misc.nix20
2 files changed, 42 insertions, 10 deletions
diff --git a/lib/meta.nix b/lib/meta.nix
index 2e817c42327d6..1a43016d27c44 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 06cb5e763e2c2..8f4a37149d92c 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;
+  };
 }