Skip to content

Changes global allocator to mimalloc, improving performance.#9415

Merged
fdncred merged 3 commits intonushell:mainfrom
FilipAndersson245:mimaloc
Jun 14, 2023
Merged

Changes global allocator to mimalloc, improving performance.#9415
fdncred merged 3 commits intonushell:mainfrom
FilipAndersson245:mimaloc

Conversation

@FilipAndersson245
Copy link
Copy Markdown
Contributor

@FilipAndersson245 FilipAndersson245 commented Jun 12, 2023

Description

this PR makes nushell use mimalloc as the default allocator, this has the benefit of reducing startup time on my machine. 17% on linux and 22% on windows, when testing using hyperfine.
the overhead to compile seem to be quite small, aswell as the increase of binary size quite small
on linux the binary went from 33.1mb to 33.2mb

linux
image

windows
image

User-Facing Changes

Tests + Formatting

After Submitting

@fdncred
Copy link
Copy Markdown
Contributor

fdncred commented Jun 12, 2023

I gave it a try on my mac but used nu --config /path/to/config.nu --env-config /path/to/env/nu --plugin-config /path/to/plugin.nu -c exit to make sure it loaded my real config. Here are the results.

Benchmark 1 - existing nushell
  Time (mean ± σ):      67.1 ms ±   1.0 ms    [User: 57.1 ms, System: 7.9 ms]
  Range (min … max):    65.3 ms …  75.4 ms    500 runs

Benchmark 2 - this pr
  Time (mean ± σ):      51.8 ms ±   0.7 ms    [User: 44.4 ms, System: 5.2 ms]
  Range (min … max):    50.3 ms …  55.8 ms    500 runs

Benchmark 2 is 1.30 ± 0.03 times faster than Benchmark 1

@FilipAndersson245
Copy link
Copy Markdown
Contributor Author

I gave it a try on my mac but used nu --config /path/to/config.nu --env-config /path/to/env/nu --plugin-config /path/to/plugin.nu -c exit to make sure it loaded my real config. Here are the results.

Benchmark 1 - existing nushell
  Time (mean ± σ):      67.1 ms ±   1.0 ms    [User: 57.1 ms, System: 7.9 ms]
  Range (min … max):    65.3 ms …  75.4 ms    500 runs

Benchmark 2 - this pr
  Time (mean ± σ):      51.8 ms ±   0.7 ms    [User: 44.4 ms, System: 5.2 ms]
  Range (min … max):    50.3 ms …  55.8 ms    500 runs

Benchmark 2 is 1.30 ± 0.03 times faster than Benchmark 1

30% faster, even better 🔥🔥🔥

@fdncred
Copy link
Copy Markdown
Contributor

fdncred commented Jun 12, 2023

Same test (with config files) on Windows 11 laptop

Benchmark 1 - existing nushell
  Time (mean ± σ):     231.9 ms ±   9.5 ms    [User: 155.7 ms, System: 36.4 ms]
  Range (min … max):   216.6 ms … 350.2 ms    500 runs

Benchmark 2 - this PR
  Time (mean ± σ):     138.4 ms ±   5.5 ms    [User: 78.9 ms, System: 19.3 ms]
  Range (min … max):   127.6 ms … 174.3 ms    500 runs

Benchmark 2 is 1.68 ± 0.10 times faster than Benchmark 1

It's a little shocking how much faster it is.

@fdncred
Copy link
Copy Markdown
Contributor

fdncred commented Jun 12, 2023

@FilipAndersson245 The current thinking is that we want to wait and try this after the next release. JT has seen some projects switch allocators and have odd issues. I'm wondering if there's any way to create tests for this allocator in order to avoid such problems?

Another question is if this allocator is supported on all our platforms that we release to.

And here's another point that was brought up, "I am not sure about is if setting the rust level global allocator messes with tooling that instruments allocations."

@FilipAndersson245
Copy link
Copy Markdown
Contributor Author

@FilipAndersson245 The current thinking is that we want to wait and try this after the next release. JT has seen some projects switch allocators and have odd issues. I'm wondering if there's any way to create tests for this allocator in order to avoid such problems?

Another question is if this allocator is supported on all our platforms that we release to.

And here's another point that was brought up, "I am not sure about is if setting the rust level global allocator messes with tooling that instruments allocations."

seems reasonable,
The supported platforms from their github does not state specific but it seem to be quite good Windows, macOS, Linux, BSD, etc.

After switching, it still works with tool such as valgrind, maybe this could be merged, and then yanked before release if it shows to produce problems 🤔.

I agree tests would be nice, I'm unsure about how the global alloc is set, as its done in the main.rs file, if it is applied to tests, and benchmarks, or just the bin.

its surprising that you got such a large reduction in startup time @fdncred. It seem alot of overhead in Nushell is from allocations.

@fdncred
Copy link
Copy Markdown
Contributor

fdncred commented Jun 12, 2023

Thanks for your other comments. I'll pass that along.

its surprising that you got such a large reduction in startup time @fdncred. It seem alot of overhead in Nushell is from allocations.

I'm assuming this is because that i'm loading a few completion files, a few modules, a few scripts where most people may not load all that stuff. But that is just a guess.

multiple platforms

We have a nightly CI that runs now. Maybe we'll be able to see if it fails tomorrow?

@FilipAndersson245
Copy link
Copy Markdown
Contributor Author

FilipAndersson245 commented Jun 12, 2023

We have a nightly CI that runs now. Maybe we'll be able to see if it fails tomorrow?

that would be nice,

I'm assuming this is because that i'm loading a few completion files, a few modules, a few scripts where most people may not load all that stuff. But that is just a guess.

Great that it performs better in more real usecases 🔥

@hustcer
Copy link
Copy Markdown
Contributor

hustcer commented Jun 12, 2023

BTW: The nightly CI may work when it's get merged to main branch

@fdncred
Copy link
Copy Markdown
Contributor

fdncred commented Jun 13, 2023

BTW: The nightly CI may work when it's get merged to main branch

I thought it was already merged?

@hustcer
Copy link
Copy Markdown
Contributor

hustcer commented Jun 13, 2023

BTW: The nightly CI may work when it's get merged to main branch

I thought it was already merged?

The nightly CI was merged, I mean this PR will be checked by the CI after it's been merged

@FilipAndersson245
Copy link
Copy Markdown
Contributor Author

FilipAndersson245 commented Jun 13, 2023

So we merge this and if problems are found we yank it before next release? @fdncred

@fdncred
Copy link
Copy Markdown
Contributor

fdncred commented Jun 14, 2023

@FilipAndersson245 I've been looking into this a bit more. Here's what I'd like to do for now. Following how qsv uses different allocators, I think it would nice to enable this functionality behind some features.

So, that would mean something like this.

mimalloc = { version = "0.1", default-features = false, optional = true }
jemallocator = { version = "0.5", optional = true }

and in the code

#[cfg(feature = "mimalloc")]
#[global_allocator]
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;

#[cfg(feature = "jemallocator")]
#[global_allocator]
static GLOBAL: jemallocator::Jemalloc = jemallocator::Jemalloc;

The difference in qsv vs nushell is that I think it would be good to initially default to the rust "standard" allocator, but have mimalloc and jemallocator in features so that we could compile with any of the 3 allocators for testing.

Searching the qsv repo also revealed this in qsv-x86_64-pc-windows-gnu.txt

The mimalloc memory allocator is not enabled on this prebuilt because of
cross-compilation limitations using GitHub's Action Runners.

Compile qsv natively on this platform if you want to use mimalloc.

@fdncred
Copy link
Copy Markdown
Contributor

fdncred commented Jun 14, 2023

One other thing. If you can make these changes, please ensure that the feature shows up when we run the version command. I think it'll be helpful seeing standard, mimalloc, or jemallocator` somehow in version. It could be with the other features or could have a "allocator" row all to itself, up to you.

@FilipAndersson245
Copy link
Copy Markdown
Contributor Author

did a comparason with jemalloc included, it beformed worse then baseline
hyperfine --warmup 50 --runs 1000 -N -L program nu,nu-mim,nu-jel "./{program} -c 'exit'" --export-markdown res.md

Command Mean [ms] Min [ms] Max [ms] Relative
./nu -c 'exit' 17.8 ± 1.2 15.8 25.6 1.15 ± 0.14
./nu-mim -c 'exit' 15.5 ± 1.6 12.8 23.3 1.00
./nu-jel -c 'exit' 19.0 ± 1.7 15.0 24.2 1.23 ± 0.17

should we include it for completeness sake?

@sholderbach
Copy link
Copy Markdown
Member

I would say no. Having two features that collide is also a cargo crime as cargo assumes that all features are additive only.

Copy link
Copy Markdown
Member

@sholderbach sholderbach left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice thanks!

@FilipAndersson245
Copy link
Copy Markdown
Contributor Author

FilipAndersson245 commented Jun 14, 2023

Should we enable the feature in some nightly build and see if something blows up?

@fdncred
Copy link
Copy Markdown
Contributor

fdncred commented Jun 14, 2023

Should we enable the feature in some nightly build and see if something blows up?

Ya, that would be good. We just added nushell/nightlies.

@fdncred fdncred merged commit 2fd4a36 into nushell:main Jun 14, 2023
@hustcer
Copy link
Copy Markdown
Contributor

hustcer commented Jun 15, 2023

Nightly release of today: https://github.com/nushell/nightly/releases/tag/nightly-b907bf3

@FilipAndersson245
Copy link
Copy Markdown
Contributor Author

Nightly release of today: https://github.com/nushell/nightly/releases/tag/nightly-b907bf3

awesome, where can we tweak the feature parameters, or is that already included in those builds?

@hustcer
Copy link
Copy Markdown
Contributor

hustcer commented Jun 15, 2023

awesome, where can we tweak the feature parameters, or is that already included in those builds?

I'm afraid we can't tweak the feature parameters currently, you can get some information from: https://github.com/nushell/nushell/blob/main/.github/workflows/release-pkg.nu

fdncred pushed a commit that referenced this pull request Sep 15, 2023
<!--
if this PR closes one or more issues, you can automatically link the PR
with
them by using one of the [*linking
keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword),
e.g.
- this PR should close #xxxx
- fixes #xxxx

you can also mention related issues, PRs or discussions!
-->

# Description
<!--
Thank you for improving Nushell. Please, check our [contributing
guide](../CONTRIBUTING.md) and talk to the core team before making major
changes.

Description of your pull request goes here. **Provide examples and/or
screenshots** if your changes affect the user experience.
-->

This PR makes `mimalloc` the default allocator, it has been the default
on the nightly builds of nushell now for a couple of months and the
performance improvements are quite nice, measuring upwards of 30% faster
startup time on Windows, and a bit smaller on Linux,
#9415

# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->

# Tests + Formatting
<!--
Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

# After Submitting
<!-- If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
-->
hardfau1t pushed a commit to hardfau1t/nushell that referenced this pull request Dec 14, 2023
<!--
if this PR closes one or more issues, you can automatically link the PR
with
them by using one of the [*linking
keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword),
e.g.
- this PR should close #xxxx
- fixes #xxxx

you can also mention related issues, PRs or discussions!
-->

# Description
<!--
Thank you for improving Nushell. Please, check our [contributing
guide](../CONTRIBUTING.md) and talk to the core team before making major
changes.

Description of your pull request goes here. **Provide examples and/or
screenshots** if your changes affect the user experience.
-->

This PR makes `mimalloc` the default allocator, it has been the default
on the nightly builds of nushell now for a couple of months and the
performance improvements are quite nice, measuring upwards of 30% faster
startup time on Windows, and a bit smaller on Linux,
nushell#9415

# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->

# Tests + Formatting
<!--
Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

# After Submitting
<!-- If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
-->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants