-
Notifications
You must be signed in to change notification settings - Fork 86
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Compile benchmarks via Nix #1119
Conversation
This allows compiling them often in CI (since it's fast), and benchmarking less often.
@@ -217,6 +217,17 @@ | |||
nickel = buildPackage "nickel-lang"; | |||
lsp-nls = buildPackage "nickel-lang-lsp"; | |||
|
|||
benchmarks = craneLib.mkCargoDerivation { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice if crane had a lib.cargoBench
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would that make sense to have benchmarks
be a function taking an attribute set { noRun ? false }
as a parameter, and appending conditionally the --no-run
parameter? It's not very different, but somehow it confines the "domain knowledge" to the mkArtifact
function (low-level commands and parameters). Any usage of benchmarks as a flake output then just has to decide noRun = true
on noRun = false
without having to leak the actual cargo commands to do so.
I think that would solve as well your other issues: you wouldn't have to override buildPhase
but could directly act on buildPhaseCargoCommand
, and you would'nt have to call mkArtifacts
a second time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That sounds like a very good plan! Only thing is that benchmarks
can't be a generic function AFAICT, it needs to be a derivation, otherwise the CLI will chocke on e.g. nix flake show
.
But this is solvable by moving the argument up to mkCraneArtifacts
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh indeed 👍 I thought this code was innside mkArtifacts
, my bad.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well in fact we are in mkArtifacts
! AFAICT, mkArtifacts
is just an internal value of the flake. It turns out right now it's only composed of derivations, but I think you can make benchmarks
a function if you'd like to 🙂 you would just have to apply it in packages
and checks
. Currently it doesn't make a big difference though, you've just extruded the function at the top of mkArtifacts
. I think that's fine too. It's theoretically less flexible (we can't reuse the same mkArtifacts
both with and without benchmark)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is what it would have to look like in practice, but it doesn't work:
diff --git a/flake.nix b/flake.nix
index 6c608754..93f9f345 100644
--- a/flake.nix
+++ b/flake.nix
@@ -182,7 +182,7 @@
# Given a rust toolchain, provide Nickel's Rust dependencies, Nickel, as
# well as rust tools (like clippy)
- mkCraneArtifacts = { rust ? mkRust { }, noRunBench ? false }:
+ mkCraneArtifacts = { rust ? mkRust { } }:
let
craneLib = crane.lib.${system}.overrideToolchain rust;
@@ -217,13 +217,13 @@
nickel = buildPackage "nickel-lang";
lsp-nls = buildPackage "nickel-lang-lsp";
- benchmarks = craneLib.mkCargoDerivation {
+ benchmarks = { noRun ? false }: craneLib.mkCargoDerivation {
inherit src cargoArtifacts;
pnameSuffix = "-bench";
buildPhaseCargoCommand = ''
- cargo bench ${pkgs.lib.optionalString noRunBench "--no-run"}
+ cargo bench ${pkgs.lib.optionalString noRun "--no-run"}
'';
doInstallCargoArtifacts = false;
@@ -386,14 +386,17 @@
done
'';
};
+ arts = mkCraneArtifacts { };
in
rec {
packages = {
- inherit (mkCraneArtifacts { })
+ inherit (arts)
nickel
- benchmarks
lsp-nls;
+
+ benchmarks = (arts.benchmarks { });
+
default = pkgs.buildEnv {
name = "nickel";
paths = [ packages.nickel packages.lsp-nls ];
@@ -420,12 +423,14 @@
};
checks = {
- inherit (mkCraneArtifacts { noRunBench = true; })
- benchmarks
+ inherit (arts)
clippy
lsp-nls
nickel
rustfmt;
+
+ benchmarks = arts.benchmarks { noRun = true; };
+
# An optimizing release build is long: eschew optimizations in checks by
# building a dev profile
nickelWasm = buildNickelWasm { profile = "dev"; };
❯ nix flake check
warning: Git tree '/home/asymmetric/code/nickel' is dirty
warning: Using saved setting for 'extra-substituters = https://tweag-nickel.cachix.org' from ~/.local/share/nix/trusted-settings.json.
warning: ignoring untrusted flake configuration setting 'extra-substituters'.
Pass '--accept-flake-config' to trust it
warning: Using saved setting for 'extra-trusted-public-keys = tweag-nickel.cachix.org-1:GIthuiK4LRgnW64ALYEoioVUQBWs0jexyoYVeLDBwRA=' from ~/.local/share/nix/trusted-settings.json.
warning: ignoring untrusted flake configuration setting 'extra-trusted-public-keys'.
Pass '--accept-flake-config' to trust it
error: value is a function while a set was expected
at /nix/store/hap5a6iw5rccl21adfxh5b3lk2c8qnmj-source/pkgs/build-support/mkshell/default.nix:19:49:
18| (attrs.${name} or [ ]) ++
19| (lib.subtractLists inputsFrom (lib.flatten (lib.catAttrs name inputsFrom)));
| ^
20|
(use '--show-trace' to show detailed location information)
Seems to be caused by benchmarks
being a function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, found the issue:
Line 243 in 68a7ab0
inputsFrom = builtins.attrValues (mkCraneArtifacts { inherit rust; }); |
We could solve it but it's starting to drag us away from the original goal of this PR. Sorry for the ping-pong. Let's do as in your previous attempt, and we'll see later about this function stuff. In any case the current flake already applies mkCraneArtifacts
several times, so this PR doesn't make anything worse in this respect.
buildPhaseCargoCommand = "cargo bench"; | ||
|
||
doCheck = false; | ||
doInstallCargoArtifacts = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is here because we don't need any of the outputs.
Instead of overriding the buildPhase, we use a function argument with optional string appending.
The default check phase has no side effects, so no need to disable it. Cf. https://crane.dev/API.html#optional-attributes-11
Thanks again! I guess the next step would be the make an output for typechecking the bench sources as well. |
This should speed up CI runs, as it reuses what's already been built and cached, and exploits build parallelism.
I've separated
cargo build
andcargo build --no-run
in the second commit. The idea is thatcargo build
(which is available as.#benchmarks
) could be used in the benchmarking workflow (although it would require patching/forkingcriterion-compare-action
). Happy to revert in case of YAGNI.Follow-up to #1104