divan 0.1.14

Statistically-comfy benchmarking library.
Documentation
# Changelog [![crates.io][crate-badge]][crate]

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic
Versioning](http://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [0.1.14] - 2024-02-17

### Fixed

- Set correct field in [`Divan::max_time`]. ([#45]https://github.com/nvzqz/divan/pull/45)

### Changes

- Improve [`args`] documentation by relating it to using [`Bencher`].

- Define [`BytesCount::of_iter`] in terms of [`BytesCount::of_many`].

## [0.1.13] - 2024-02-09

### Fixed

- Missing update to `divan-macros` dependency.

## [0.1.12] - 2024-02-09

### Added

- Display [`args`] option values with [`Debug`] instead if [`ToString`] is not
  implemented.

  This makes it simple to use enums with derived [`Debug`]:

  ```rs
  #[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.

## [0.1.11] - 2024-01-20

### Fixed

- Sorting negative [`args`] numbers.

## [0.1.10] - 2024-01-20

### Fixed

- Sort [`args`] numbers like [`consts`].

## [0.1.9] - 2024-01-20

### Added

- [`args`] option for providing runtime arguments to benchmarks:

  ```rs
  #[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:
  - It is compatible with more types, only requiring that the argument type
    implements [`Any`], [`Copy`], [`Send`], [`Sync`], and [`ToString`]. [`Copy`]
    is not needed if the argument is used through a reference.
  - It does not increase compile times, unlike [`consts`] which needs to
    generate new code for each constant used.

## [0.1.8] - 2023-12-19

### Changes

- 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.

### Fixed

- Remove unused allocations if [`AllocProfiler`] is not active as the global
  allocator.

## [0.1.7] - 2023-12-13

### Changes

- Improve [`AllocProfiler`] implementation documentation.

- Limit [`AllocProfiler`] mean count outputs to 4 significant digits to not be
  very wide and for consistency with other outputs.

## [0.1.6] - 2023-12-13

### Added

- [`AllocProfiler`] allocator that tracks allocation counts and sizes during
  benchmarks.

## [0.1.5] - 2023-12-05

### Added

- [`black_box_drop`]https://docs.rs/divan/0.1.5/divan/fn.black_box_drop.html
  convenience function for [`black_box`] + [`drop`][drop_fn]. This is useful
  when benchmarking a lazy [`Iterator`] to completion with `for_each`:

  ```rust
  #[divan::bench]
  fn parse_iter() {
      let input: &str = // ...

      Parser::new(input)
          .for_each(divan::black_box_drop);
  }
  ```

## [0.1.4] - 2023-12-02

### Added

- `From` implementations for counters on references to `u8``u64` and `usize`,
  such as `From<&u64>` and `From<&&u64>`. This allows for doing:

  ```rust
  bencher
      .with_inputs(|| { ... })
      .input_counter(ItemsCount::from)
      .bench_values(|n| { ... });
  ```

- [`Bencher::count_inputs_as<C>`]https://docs.rs/divan/0.1.4/divan/struct.Bencher.html#method.count_inputs_as
  method to convert inputs to a `Counter`:

  ```rust
  bencher
      .with_inputs(|| -> usize {
          // ...
      })
      .count_inputs_as::<ItemsCount>()
      .bench_values(|n| -> Vec<usize> {
          (0..n).collect()
      });
  ```

## [0.1.3] - 2023-11-21

### Added

- Convenience shorthand options for `#[divan::bench]` and
  `#[divan::bench_group]` counters:
  - [`bytes_count`]https://docs.rs/divan/0.1.3/divan/attr.bench.html#bytes_count
    for `counter = BytesCount::from(n)`
  - [`chars_count`]https://docs.rs/divan/0.1.3/divan/attr.bench.html#chars_count
    for `counter = CharsCount::from(n)`
  - [`items_count`]https://docs.rs/divan/0.1.3/divan/attr.bench.html#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`]https://docs.rs/divan/0.1.3/divan/struct.Divan.html#method.threads
  - `--threads A B C...` CLI arg
  - `DIVAN_THREADS=A,B,C` env var

  The following example will benchmark across 2, 4, and [available parallelism]
  thread counts:

  ```sh
  DIVAN_THREADS=0,2,4 cargo bench -q -p examples --bench atomic
  ```

- Set global
  [`Counter`s]https://docs.rs/divan/0.1.3/divan/counter/trait.Counter.html at
  runtime using:
  - [`Divan::counter`]https://docs.rs/divan/0.1.3/divan/struct.Divan.html#method.counter
  - [`Divan::items_count`]https://docs.rs/divan/0.1.3/divan/struct.Divan.html#method.items_count
  - [`Divan::bytes_count`]https://docs.rs/divan/0.1.3/divan/struct.Divan.html#method.bytes_count
  - [`Divan::chars_count`]https://docs.rs/divan/0.1.3/divan/struct.Divan.html#method.chars_count
  - `--items-count N` CLI arg
  - `--bytes-count N` CLI arg
  - `--chars-count N` CLI arg
  - `DIVAN_ITEMS_COUNT=N` env var
  - `DIVAN_BYTES_COUNT=N` env var
  - `DIVAN_CHARS_COUNT=N` env var

- `From<C>` for
  [`ItemsCount`]https://docs.rs/divan/0.1.3/divan/counter/struct.ItemsCount.html,
  [`BytesCount`]https://docs.rs/divan/0.1.3/divan/counter/struct.BytesCount.html,
  and
  [`CharsCount`]https://docs.rs/divan/0.1.3/divan/counter/struct.CharsCount.html
  where `C` is `u8``u64` or `usize` (via `CountUInt` internally). This provides
  an alternative to the `new` constructor.

- [`BytesCount::of_many`]https://docs.rs/divan/0.1.3/divan/counter/struct.BytesCount.html#method.of_many
  method similar to [`BytesCount::of`]https://docs.rs/divan/0.1/divan/counter/struct.BytesCount.html#method.of,
  but with a parameter by which to multiply the size of the type.

- [`BytesCount::u64`]https://docs.rs/divan/0.1.3/divan/counter/struct.BytesCount.html#method.u64,
  [`BytesCount::f64`]https://docs.rs/divan/0.1.3/divan/counter/struct.BytesCount.html#method.f64,
  and similar methods based on [`BytesCount::of_many`]https://docs.rs/divan/0.1.3/divan/counter/struct.BytesCount.html#method.of_many.

### Removed

- [`black_box`] inside benchmark loop when deferring [`Drop`] of outputs. This
  is now done after the loop.

- [`linkme`]https://docs.rs/linkme dependency in favor of pre-`main` to
  register benchmarks and benchmark groups. This is generally be more portable
  and reliable.

### Changed

- Now calling [`black_box`] at the end of the benchmark loop when deferring use
  of inputs or [`Drop`] of outputs.

## [0.1.2] - 2023-10-28

### Fixed

- 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

### Fixed

- Fix using LLD as linker for Linux by using the same pre-`main` approach as
  Windows.

## 0.1.0 - 2023-10-04

Initial release. See [blog post](https://nikolaivazquez.com/blog/divan/).

[crate]:       https://crates.io/crates/divan
[crate-badge]: https://img.shields.io/crates/v/divan.svg

[Unreleased]: https://github.com/nvzqz/divan/compare/v0.1.14...HEAD
[0.1.14]: https://github.com/nvzqz/divan/compare/v0.1.13...v0.1.14
[0.1.13]: https://github.com/nvzqz/divan/compare/v0.1.12...v0.1.13
[0.1.12]: https://github.com/nvzqz/divan/compare/v0.1.11...v0.1.12
[0.1.11]: https://github.com/nvzqz/divan/compare/v0.1.10...v0.1.11
[0.1.10]: https://github.com/nvzqz/divan/compare/v0.1.9...v0.1.10
[0.1.9]: https://github.com/nvzqz/divan/compare/v0.1.8...v0.1.9
[0.1.8]: https://github.com/nvzqz/divan/compare/v0.1.7...v0.1.8
[0.1.7]: https://github.com/nvzqz/divan/compare/v0.1.6...v0.1.7
[0.1.6]: https://github.com/nvzqz/divan/compare/v0.1.5...v0.1.6
[0.1.5]: https://github.com/nvzqz/divan/compare/v0.1.4...v0.1.5
[0.1.4]: https://github.com/nvzqz/divan/compare/v0.1.3...v0.1.4
[0.1.3]: https://github.com/nvzqz/divan/compare/v0.1.2...v0.1.3
[0.1.2]: https://github.com/nvzqz/divan/compare/v0.1.1...v0.1.2
[0.1.1]: https://github.com/nvzqz/divan/compare/v0.1.0...v0.1.1

[`AllocProfiler`]: https://docs.rs/divan/0.1/divan/struct.AllocProfiler.html
[`args`]: https://docs.rs/divan/latest/divan/attr.bench.html#args
[`Bencher`]: https://docs.rs/divan/0.1/divan/struct.Bencher.html
[`black_box`]: https://docs.rs/divan/latest/divan/fn.black_box.html
[`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
[`consts`]: https://docs.rs/divan/latest/divan/attr.bench.html#consts
[`Divan::max_time`]: https://docs.rs/divan/0.1/divan/struct.Divan.html#method.max_time

[`Any`]: https://doc.rust-lang.org/std/any/trait.Any.html
[`Copy`]: https://doc.rust-lang.org/std/marker/trait.Copy.html
[`Debug`]: https://doc.rust-lang.org/std/fmt/trait.Debug.html
[`Drop`]: https://doc.rust-lang.org/std/ops/trait.Drop.html
[`Iterator`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html
[`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html
[`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
[`ToString`]: https://doc.rust-lang.org/std/string/trait.ToString.html
[available parallelism]: https://doc.rust-lang.org/std/thread/fn.available_parallelism.html
[drop_fn]: https://doc.rust-lang.org/std/mem/fn.drop.html
[`thread_local!`]: https://doc.rust-lang.org/std/macro.thread_local.html

[`pthread_key_create`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_key_create.html