diff --git a/doc/manual/rl-next/mimalloc.md b/doc/manual/rl-next/mimalloc.md new file mode 100644 index 000000000..b16c290d8 --- /dev/null +++ b/doc/manual/rl-next/mimalloc.md @@ -0,0 +1,16 @@ +--- +synopsis: "Use mimalloc for faster evaluation" +cls: [5645] +category: Features +credits: [getchoo, lovesegfault] +--- + +Lix now links with [mimalloc](https://github.com/microsoft/mimalloc), +replacing the system's default `malloc()` for all non-GC allocations. + +This yields a **5–12% wall-clock improvement** on evaluation workloads, +ranging from `nix-instantiate hello` to `nix-env -qa` and full NixOS +configurations. + +The allocator can be disabled at build time with `-Dmimalloc=disabled`, +or by passing the `useMimalloc = false` override to the `lix` package. diff --git a/lix/nix/meson.build b/lix/nix/meson.build index 1e25ea143..155920a32 100644 --- a/lix/nix/meson.build +++ b/lix/nix/meson.build @@ -172,6 +172,7 @@ nix = executable( dependencies : [ liblix, boehm, + mimalloc, capnp_rpc, nlohmann_json, kj, diff --git a/meson.build b/meson.build index f306d74df..a5833eaaa 100644 --- a/meson.build +++ b/meson.build @@ -352,6 +352,8 @@ gc_opt = get_option('gc').disable_if( boehm = dependency('bdw-gc', required : gc_opt, version : '>=8.2.6', include_type : 'system') configdata.set('HAVE_BOEHMGC', boehm.found().to_int()) +mimalloc = dependency('mimalloc', required: get_option('mimalloc')) + boost = dependency('boost', required : true, include_type : 'system') kj = dependency('kj-async', required : true, include_type : 'system') capnp = dependency('capnp', required : true, include_type : 'system') diff --git a/meson.options b/meson.options index 573589d16..6c194ccaf 100644 --- a/meson.options +++ b/meson.options @@ -8,6 +8,10 @@ option('gc', type : 'feature', description : 'enable garbage collection in the Nix expression evaluator (requires Boehm GC)', ) +option('mimalloc', type: 'feature', value: 'auto', + description: 'link against mimalloc to override the default memory allocator', +) + option('enable-embedded-sandbox-shell', type : 'boolean', value : false, description : 'include the sandbox shell in the Nix binary', ) diff --git a/package.nix b/package.nix index a7e67d353..f893e7c22 100644 --- a/package.nix +++ b/package.nix @@ -42,6 +42,7 @@ cacert, mercurial, meson, + mimalloc, ninja, openssl, passt, @@ -75,6 +76,9 @@ # Support garbage collection in the evaluator. enableGC ? sanitize == null || !builtins.elem "address" sanitize, + # Whether to use mimalloc over the default `malloc` + # Significantly improves evaluation performance on allocation-heavy workloads + useMimalloc ? true, # List of Meson sanitize options. Accepts values of b_sanitize, e.g. # "address", "undefined", "thread". # Enabling the "address" sanitizer will disable garbage collection in the evaluator. @@ -467,6 +471,7 @@ stdenv.mkDerivation (finalAttrs: { # so we must explicitly enable or disable features that we are not passing # dependencies for. (lib.mesonEnable "gc" enableGC) + (lib.mesonEnable "mimalloc" useMimalloc) (lib.mesonEnable "internal-api-docs" internalApiDocs) (lib.mesonEnable "dtrace-probes" withDtrace) (lib.mesonBool "enable-tests" (finalAttrs.finalPackage.doCheck || lintInsteadOfBuild)) @@ -574,7 +579,8 @@ stdenv.mkDerivation (finalAttrs: { ++ lib.optionals (finalAttrs.dontBuild) maybePropagatedInputs # I am so sorry. This is because checkInputs are required to pass # configure, but we don't actually want to *run* the checks here. - ++ lib.optionals lintInsteadOfBuild finalAttrs.checkInputs; + ++ lib.optionals lintInsteadOfBuild finalAttrs.checkInputs + ++ lib.optional useMimalloc mimalloc; checkInputs = [ gtest