c94777fc54
When performing a noop sync, we don't need the rayon threadpool, yet we pay for its initialization:  Be making the initialization lazy, we avoid that cost:  This code runs every time before user code in `uv run`. This means that before calling rayon, one now needs to call `LazyLock::force(&RAYON_INITIALIZE);`. Performance mode (CPU 0 is a perf core): ``` $ taskset -c 0 hyperfine --warmup 5 -N "/home/konsti/projects/uv/uv-main sync" "/home/konsti/projects/uv/target/profiling/uv sync" Benchmark 1: /home/konsti/projects/uv/uv-main sync Time (mean ± σ): 4.5 ms ± 0.1 ms [User: 2.7 ms, System: 1.8 ms] Range (min … max): 4.4 ms … 6.4 ms 640 runs Warning: Statistical outliers were detected. Consider re-running this benchmark on a quiet system without any interferences from other programs. It might help to use the '--warmup' or '--prepare' options. Benchmark 2: /home/konsti/projects/uv/target/profiling/uv sync Time (mean ± σ): 4.4 ms ± 0.1 ms [User: 2.7 ms, System: 1.6 ms] Range (min … max): 4.3 ms … 5.0 ms 679 runs Summary /home/konsti/projects/uv/target/profiling/uv sync ran 1.03 ± 0.04 times faster than /home/konsti/projects/uv/uv-main sync ``` Power saver mode: ``` $ hyperfine --warmup 5 -N "/home/konsti/projects/uv/uv-main sync" "/home/konsti/projects/uv/target/profiling/uv sync" Benchmark 1: /home/konsti/projects/uv/uv-main sync Time (mean ± σ): 28.1 ms ± 1.2 ms [User: 15.5 ms, System: 20.3 ms] Range (min … max): 25.7 ms … 31.9 ms 102 runs Benchmark 2: /home/konsti/projects/uv/target/profiling/uv sync Time (mean ± σ): 24.0 ms ± 1.2 ms [User: 13.8 ms, System: 9.9 ms] Range (min … max): 22.2 ms … 28.2 ms 122 runs Summary /home/konsti/projects/uv/target/profiling/uv sync ran 1.17 ± 0.08 times faster than /home/konsti/projects/uv/uv-main sync ```
22 lines
882 B
Rust
22 lines
882 B
Rust
//! Initialize the rayon threadpool once, before we need it.
|
|
//!
|
|
//! The `uv` crate sets [`RAYON_PARALLELISM`] from the user settings, and the extract and install
|
|
//! code initialize the threadpool lazily only if they are actually used by calling
|
|
//! `LazyLock::force(&RAYON_INITIALIZE)`.
|
|
|
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
|
use std::sync::LazyLock;
|
|
|
|
/// The number of threads for the rayon threadpool.
|
|
///
|
|
/// The default of 0 makes rayon use its default.
|
|
pub static RAYON_PARALLELISM: AtomicUsize = AtomicUsize::new(0);
|
|
|
|
/// Initialize the threadpool lazily. Always call before using rayon the potentially first time.
|
|
pub static RAYON_INITIALIZE: LazyLock<()> = LazyLock::new(|| {
|
|
rayon::ThreadPoolBuilder::new()
|
|
.num_threads(RAYON_PARALLELISM.load(Ordering::SeqCst))
|
|
.build_global()
|
|
.expect("failed to initialize global rayon pool");
|
|
});
|