All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog and this project adheres to Semantic Versioning.
-
Renamed default
Unitinput generator type inBenchertoNoInput. -
Made the thread pool be per-run instead of global.
0.1.21 - 2025-04-09
Divan::skip_exactbehaved incorrectly inv0.1.19.
- Improved handling of internal code around filters and those responsible for sacking the people who have just been sacked have been sacked.
0.1.20 - 2025-04-09
Divan::skip_regexaccidentally droppedregex_lite::Regexand behaved incorrectly inv0.1.19.
0.1.19 - 2025-04-09
cargo-nextestno longer skips benchmarks with argument parameters (#75).
- Organized positive and negative filters into a split buffer.
0.1.18 - 2025-04-05
-
Support for
cargo-nextestrunning benchmarks as tests. -
preludemodule for simplifying imports of#[bench],#[bench_group],black_box,black_box_drop,AllocProfiler,Bencher, andDivan. -
Support
wasiandemscriptentargets.
0.1.17 - 2024-12-04
-
Set MSRV to 1.80 for
LazyLockand newsize_ofprelude import. -
Reduced thread pool memory usage by many kilobytes by using rendezvous channels instead of array-based channels.
0.1.16 - 2024-11-25
-
Thread pool for reusing threads across multi-threaded benchmarks. The result is that when running Divan benchmarks under a sampling profiler, the profiler's output will be cleaner and easier to understand. (#37)
-
Track the maximum number of allocations during a benchmark.
-
Make private
Arg::gettrait method not takeself, so that text editors don't recommend using it. (#59) -
Cache
BenchOptionsusingLazyLockinstead ofOnceLock, saving space and simplifying the implementation.
0.1.15 - 2024-10-31
-
CyclesCountcounter to display cycle throughput as Hertz. -
Track the maximum number of bytes allocated during a benchmark.
- Remove
has_cpuidpolyfill due to it no longer being planned for Rust, since CPUID is assumed to be available on all old x86 Rust targets.
-
List generic benchmark type parameter
A<4>beforeA<32>. (#64) -
Improve precision by using
f64when calculating allocation count and sizes for the median samples. -
Multi-thread allocation counting in
sum_alloc_tallieson macOS was loading a null pointer instead of the pointer initialized bysync_threads.
-
Sort all output benchmark names naturally instead of lexicographically.
-
Internally reuse
&[&str]slice forargsnames. -
Subtract overhead of
AllocProfilerfrom timings. Now that Divan also tracks the maximum bytes allocated, the overhead was apparent in timings. -
Simplify
ThreadAllocInfo::clear. -
Move measured loop overhead from
SharedContextto globalOnceLock. -
Macros no longer rely on
stdbeing re-exported by Divan. Instead they use::stdor::coreto greatly simplify code. Although this is technically a breaking change, it is extremely unlikely to doextern crate std as x.
0.1.14 - 2024-02-17
- Set correct field in
Divan::max_time. (#45)
-
Define
BytesCount::of_iterin terms ofBytesCount::of_many.
0.1.13 - 2024-02-09
- Missing update to
divan-macrosdependency.
0.1.12 - 2024-02-09
-
Display
argsoption values withDebuginstead ifToStringis not implemented.This makes it simple to use enums with derived
Debug:#[derive(Debug)] enum Arg { A, B } #[divan::bench(args = [Arg::A, Arg::B])] fn bench_args(arg: &Arg) { ... }
-
Documentation of when to use
black_boxin benchmarks.
0.1.11 - 2024-01-20
- Sorting negative
argsnumbers.
0.1.10 - 2024-01-20
0.1.9 - 2024-01-20
-
argsoption for providing runtime arguments to benchmarks:#[divan::bench(args = [1, 2, 3])] fn args_list(arg: usize) { ... } #[divan::bench(args = 1..=3)] fn args_range(arg: usize) { ... } const ARGS: &[usize] = [1, 2, 3]; #[divan::bench(args = ARGS)] fn args_const(arg: usize) { ... }
This option may be preferred over the similar
constsoption because:
0.1.8 - 2023-12-19
-
Reduce
AllocProfilerfootprint from 6-10ns to 1-2ns:-
Thread-local values are now exclusively owned by their threads and are no longer kept in a global list. This enables some optimizations:
-
Performing faster unsynchronized arithmetic.
-
Removing one level of pointer indirection by storing the thread-local value entirely inline in
thread_local!, rather than storing a pointer to a globally-shared instance. -
Compiler emits SIMD arithmetic for x86_64 using
paddq.
-
-
Improved thread-local lookup on x86_64 macOS by using a static lookup key instead of a dynamic key from
pthread_key_create. Key 11 is used because it is reserved for Windows.The
dyn_thread_localcrate feature disables this optimization. This is recommended if your code or another dependency uses the same static key.
-
- Remove unused allocations if
AllocProfileris not active as the global allocator.
0.1.7 - 2023-12-13
-
Improve
AllocProfilerimplementation documentation. -
Limit
AllocProfilermean count outputs to 4 significant digits to not be very wide and for consistency with other outputs.
0.1.6 - 2023-12-13
AllocProfilerallocator that tracks allocation counts and sizes during benchmarks.
0.1.5 - 2023-12-05
-
black_box_dropconvenience function forblack_box+drop. This is useful when benchmarking a lazyIteratorto completion withfor_each:#[divan::bench] fn parse_iter() { let input: &str = // ... Parser::new(input) .for_each(divan::black_box_drop); }
0.1.4 - 2023-12-02
-
Fromimplementations for counters on references tou8–u64andusize, such asFrom<&u64>andFrom<&&u64>. This allows for doing:bencher .with_inputs(|| { ... }) .input_counter(ItemsCount::from) .bench_values(|n| { ... }); -
Bencher::count_inputs_as<C>method to convert inputs to aCounter:bencher .with_inputs(|| -> usize { // ... }) .count_inputs_as::<ItemsCount>() .bench_values(|n| -> Vec<usize> { (0..n).collect() });
0.1.3 - 2023-11-21
-
Convenience shorthand options for
#[divan::bench]and#[divan::bench_group]counters:bytes_countforcounter = BytesCount::from(n)chars_countforcounter = CharsCount::from(n)items_countforcounter = ItemsCount::from(n)
-
Support for NetBSD, DragonFly BSD, and Haiku OS by using pre-
main. -
Set global thread counts using:
Divan::threads--threads A B C...CLI argDIVAN_THREADS=A,B,Cenv var
The following example will benchmark across 2, 4, and available parallelism thread counts:
DIVAN_THREADS=0,2,4 cargo bench -q -p examples --bench atomic
-
Set global
Counters at runtime using:Divan::counterDivan::items_countDivan::bytes_countDivan::chars_count--items-count NCLI arg--bytes-count NCLI arg--chars-count NCLI argDIVAN_ITEMS_COUNT=Nenv varDIVAN_BYTES_COUNT=Nenv varDIVAN_CHARS_COUNT=Nenv var
-
From<C>forItemsCount,BytesCount, andCharsCountwhereCisu8–u64orusize(viaCountUIntinternally). This provides an alternative to thenewconstructor. -
BytesCount::of_manymethod similar toBytesCount::of, but with a parameter by which to multiply the size of the type. -
BytesCount::u64,BytesCount::f64, and similar methods based onBytesCount::of_many.
-
black_boxinside benchmark loop when deferringDropof outputs. This is now done after the loop. -
linkmedependency in favor of pre-mainto register benchmarks and benchmark groups. This is generally be more portable and reliable.
- Now calling
black_boxat the end of the benchmark loop when deferring use of inputs orDropof outputs.
0.1.2 - 2023-10-28
- Multi-threaded benchmarks being spread across CPUs, instead of pinning the main thread to CPU 0 and having all threads inherit the main thread's affinity.
0.1.1 - 2023-10-25
- Fix using LLD as linker for Linux by using the same pre-
mainapproach as Windows.
Initial release. See blog post.