Skip to content

Commit

Permalink
perf: bring musl binaries performance in par with glibc ones
Browse files Browse the repository at this point in the history
After profiling, I have confirmed that the cause of the relative
slowdown of `musl` binaries with respect to `glibc` was the usage of a
slower memory allocator in the `musl` case, which critically affects the
performance of Zopfli compression, especially on CPUs with lots of
physical threads.
  • Loading branch information
AlexTMjugador committed Sep 17, 2023
1 parent 35c8259 commit 3a10205
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 0 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,18 @@ Versioning](https://semver.org/spec/v2.0.0.html).
to their decentralized and free nature, the PackSquash project will most
likely not pursue signing binaries with code signing certificates.

#### Performance

- The statically-linked PackSquash CLI Linux binaries now use the
[`mimalloc`](https://github.com/microsoft/mimalloc) memory allocator, instead
of the default `musl` C library allocator.
- This brings the performance of such binaries roughly in line with those
packaged for Debian, which dynamically link against `glibc`. Previously,
slowdowns of 5x or more could be expected, depending on the number of
threads used.
- Because they use statically-linked binaries, the PackSquash GitHub
Action and Docker container also saw performance improvements.

#### Fixed

- The UTF-8 BOM is no longer automatically stripped from properties files, as
Expand Down
20 changes: 20 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions packages/packsquash_cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ env_logger = { version = "0.10.0", default-features = false, features = ["color"
winapi = { version = "0.3.9", default-features = false, features = ["consoleapi"] }
winapi-util = "0.1.5"

[target.'cfg(all(target_os = "linux", target_env = "musl"))'.dependencies]
# The mimalloc C malloc override feature is troublesome on macOS and Windows, but
# luckily the Linux musl C library should support this well. See:
# https://github.com/purpleprotocol/mimalloc_rust/issues/41
# We are interested in overriding malloc because we depend on C libraries, and doing
# so buys us a safety net against mismatching memory managed by different allocators,
# in addition to keep binary sizes down
mimalloc = { version = "0.1.39", default-features = false, features = ["override"] }

[target.'cfg(windows)'.build-dependencies]
winresource = "0.1.17"

Expand Down
9 changes: 9 additions & 0 deletions packages/packsquash_cli/src/bin/packsquash/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,15 @@ const LOG_TARGET: Target = Target::Stderr;
/// A producer of the [`IsTerminal`] implementation that matches the [`LOG_TARGET`] constant.
const LOG_TARGET_STREAM: fn() -> Stderr = io::stderr;

/// Zopfli compression is pretty intensive on the memory allocator, and musl
/// is known to use a simple but prone to extreme thread contention allocator.
/// Replace its allocator with one whose performance is close to glibc so that
/// the PackSquash CLI musl binaries have a similar performance to glibc
/// binaries; otherwise, slowdowns of 5x or more are to be expected.
#[cfg(all(target_os = "linux", target_env = "musl"))]
#[global_allocator]
static GLOBAL_ALLOCATOR: mimalloc::MiMalloc = mimalloc::MiMalloc;

fn main() {
process::exit(run(TerminalTitleController::new()));
}
Expand Down

0 comments on commit 3a10205

Please sign in to comment.