NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
crates.io · #2661 most downloaded on crates.io
Macros for Divan, a statistically-comfy benchmarking library.
Last release 1 years ago
no release in 18 months
Ships unpredictably
gaps range from 9 days to 9 months
Nearly every release is documented
notes for 22 of 23 stable releases
Nothing withdrawn
no release was ever pulled
3 years old
23 releases · first in 2023
One column per quarter.
Divan::skip_exact behaved incorrectly in v0.1.19.
Divan::skip_exact behaved incorrectly in v0.1.19.Divan::skip_regex accidentally dropped `regex_lite::Regex` and behaved incorrectly in v0.1.19.
Divan::skip_regex accidentally dropped
regex_lite::Regex
and behaved incorrectly in v0.1.19.[cargo-nextest] no longer skips benchmarks with argument parameters ([#75]).
cargo-nextest] no longer skips benchmarks with argument parameters ([#75]).Support for [cargo-nextest] running benchmarks as tests.
Support for [cargo-nextest] running benchmarks as tests.
[prelude] module for simplifying imports of [#[bench]][bench_attr],
[#[bench_group]][bench_group_attr], [black_box], [black_box_drop],
[AllocProfiler], [Bencher], and [Divan].
Support wasi and emscripten targets.
Set [MSRV] to 1.80 for [LazyLock] and new size_of prelude import.
Set [MSRV] to 1.80 for [LazyLock] and new size_of prelude import.
Reduced thread pool memory usage by many kilobytes by using rendezvous channels instead of array-based channels.
Thread pool for reusing threads across multi-threaded benchmarks. The result is that when running Divan benchmarks under a sampling profiler, the prof
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::get trait method not take self, so that text editors
don't recommend using it. ([#59])
Cache BenchOptions using LazyLock instead of OnceLock, saving space and
simplifying the implementation.
Instead they use ::std or ::core to greatly simplify code. Although this is technically a breaking change, it is extremely unlikely to do extern crate…
[CyclesCount] counter to display cycle throughput as Hertz.
Track the maximum number of bytes allocated during a benchmark.
has_cpuid polyfill 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> before A<32>. ([#64])
Improve precision by using f64 when calculating allocation count and sizes
for the median samples.
Multi-thread allocation counting in sum_alloc_tallies on macOS was loading a
null pointer instead of the pointer initialized by sync_threads.
Sort all output benchmark names naturally instead of lexicographically.
Internally reuse [&[&str] slice][slice] for [args] names.
Subtract overhead of [AllocProfiler] from timings. Now that Divan also
tracks the maximum bytes allocated, the overhead was apparent in timings.
Simplify ThreadAllocInfo::clear.
Move measured loop overhead from SharedContext to global OnceLock.
Macros no longer rely on std being re-exported by Divan. Instead they use
::std or ::core to greatly simplify code. Although this is technically a
breaking change, it is extremely unlikely to do extern crate std as x.
Set correct field in [Divan::max_time].
Divan::max_time]. (#45)Improve [args] documentation by relating it to using [Bencher].
Define [BytesCount::of_iter] in terms of [BytesCount::of_many].
Missing update to divan-macros dependency.
divan-macros dependency.Display [args] option values with [Debug] instead if [ToString] is not implemented.
Display [args] option values with [Debug] instead if [ToString] is 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_box] in benchmarks.
Sorting negative [args] numbers.
args] numbers.Sort [args] numbers like [consts].
args] numbers like [consts].[args] option for providing runtime arguments to benchmarks:
[args] option 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 [consts] option because:
Any], [Copy], [Send], [Sync], and [ToString]. [Copy]
is not needed if the argument is used through a reference.consts] which needs to
generate new code for each constant used.Reduce [AllocProfiler] footprint from 6-10ns to 1-2ns:
Reduce [AllocProfiler] footprint 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_local crate feature disables this optimization. This is
recommended if your code or another dependency uses the same static key.
AllocProfiler] is not active as the global
allocator.Improve [AllocProfiler] implementation documentation.
Improve [AllocProfiler] implementation documentation.
Limit [AllocProfiler] mean count outputs to 4 significant digits to not be
very wide and for consistency with other outputs.
[AllocProfiler] allocator that tracks allocation counts and sizes during benchmarks.
AllocProfiler] allocator that tracks allocation counts and sizes during
benchmarks.[black_box_drop] convenience function for [black_box] + [drop]. This is useful when benchmarking a lazy [Iterator] to completion with for_each:
[black_box_drop] convenience function for [black_box] + [drop]. This is
useful when benchmarking a lazy [Iterator] to completion with for_each:
#[divan::bench]
fn parse_iter() {
let input: &str = // ...
Parser::new(input)
.for_each(divan::black_box_drop);
}
From implementations for counters on references to u8–u64 and usize, such as From<&u64> and From<&&u64>. This allows for doing:
From implementations for counters on references to u8–u64 and usize,
such as From<&u64> and From<&&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 a Counter:
bencher
.with_inputs(|| -> usize {
// ...
})
.count_inputs_as::<ItemsCount>()
.bench_values(|n| -> Vec<usize> {
(0..n).collect()
});
Convenience shorthand options for #[divan::bench] and #[divan::bench_group] counters:
Convenience shorthand options for #[divan::bench] and
#[divan::bench_group] counters:
bytes_count
for counter = BytesCount::from(n)chars_count
for counter = CharsCount::from(n)items_count
for counter = 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,C env varThe 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 N CLI arg--bytes-count N CLI arg--chars-count N CLI argDIVAN_ITEMS_COUNT=N env varDIVAN_BYTES_COUNT=N env varDIVAN_CHARS_COUNT=N env varFrom<C> for
ItemsCount,
BytesCount,
and
CharsCount
where C is u8–u64 or usize (via CountUInt internally). This provides
an alternative to the new constructor.
BytesCount::of_many
method similar to BytesCount::of,
but with a parameter by which to multiply the size of the type.
BytesCount::u64,
BytesCount::f64,
and similar methods based on BytesCount::of_many.
[black_box] inside benchmark loop when deferring [Drop] of outputs. This
is now done after the loop.
linkme dependency in favor of pre-main to
register benchmarks and benchmark groups. This is generally be more portable
and reliable.
black_box] at the end of the benchmark loop when deferring use
of inputs or [Drop] of outputs.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 affin
Fix using LLD as linker for Linux by using the same pre-main approach as Windows.
main approach as
Windows.Initial release. See blog post.
Initial release. See blog post.
<!-- Stable -->
[AllocProfiler]: https://docs.rs/divan/latest/divan/struct.AllocProfiler.html
[args]: https://docs.rs/divan/latest/divan/attr.bench.html#args
[Bencher]: https://docs.rs/divan/latest/divan/struct.Bencher.html
[black_box_drop]: https://docs.rs/divan/latest/divan/fn.black_box_drop.html
[black_box]: https://docs.rs/divan/latest/divan/fn.black_box.html
[consts]: https://docs.rs/divan/latest/divan/attr.bench.html#consts
[Divan::max_time]: https://docs.rs/divan/latest/divan/struct.Divan.html#method.max_time
[Divan]: https://docs.rs/divan/latest/divan/struct.Divan.html
[prelude]: https://docs.rs/divan/latest/divan/prelude/index.html
[bench_attr]: https://docs.rs/divan/latest/divan/attr.bench.html
[bench_group_attr]: https://docs.rs/divan/latest/divan/attr.bench_group.html
<!-- 0.1 -->
[BytesCount::of_iter]: https://docs.rs/divan/0.1/divan/counter/struct.BytesCount.html#method.of_iter
[BytesCount::of_many]: https://docs.rs/divan/0.1/divan/counter/struct.BytesCount.html#method.of_many
[CyclesCount]: https://docs.rs/divan/0.1/divan/counter/struct.CyclesCount.html
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →