Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Things on this page are fragmentary and immature notes/thoughts of the author. Please read with your own judgement!

Tips and Traps

  1. Rust’s built-in benchmark feature has been unstable (on nightly channel only) for many years and will likely be deprecated.

  1. criterion was the most popular choice for benchmarking code.

  2. divan is a newer modern alternative to criterion with many more features.

  3. Gungraun is another rising tool for benching Rust code. It leverages Valgrind’s profiling tools like Callgrind, Cachegrind and DHAT to provide extremely accurate and consistent measurements of Rust code, making it perfectly suited to run in environments like a CI.

Rust Benchmarking Tool Comparison

Feature

Criterion

Divan

Gungraun

Measurement

Wall-clock time

Wall-clock time

Instruction counts / Cache misses

CPU Cycles

via criterion-perf-events [1]

Built-in support via TSC for x86.

Built-in support for estimated CPU cycles.

Method

Statistical (100+ runs)

Statistical (100+ runs)

One-shot (via Valgrind)

Noise

Sensitive to OS jitter

Sensitive to OS jitter

Zero noise (Deterministic)

Reports

HTML Graphs / Console

Console / Memory usage

Callgrind / Flamegraphs

Setup

High boilerplate

Very Low (Attributes)

Moderate (Requires Valgrind)

Platform

Cross-platform

Cross-platform

Linux/macOS only

Criterion

  1. With Rust stable, Criterion can only benchmark public functions/methods .

  2. Criterion supports the same filtering behavior that the standard-library testing and benchmarking tools support, so you should be able to just run cargo bench NAME and it will only run benchmarks with “NAME” in the benchmark name or function name.

  3. Even if Criterion is currently the best available benchmarking tool available in Rust, it still have a few issues.

    • It can only benchmark public functions/methods with Rust stable

    • If you benchmark WALL/CPU times, the benchmark results of the same function (without code change) might vary significantly with 2 benchmarks running at very close times. It is suggested that you benchmark Linux perf events instead, which gives you stable benchmark results.

  4. There are lots of Criterion extensions enhancing features of Criterion.

divan

divan is a fast and simple benchmarking for Rust projects.

Gungraun

Benchmark Numbers for Rust

Infographics: Operation Costs in CPU Clock Cycles

Introduction to C and Computer Organization

random access of an element of array,

my impression is that it’s about 6-7 CPU cycles (including bound check). get_unchecked (without bound check) takes about 4 CPU cycles (verify this)

How much does an array access cost?

multiplication of an non-const integer with a const integer: 4.5 cpu cycles

multiplication of 2 non-const usize: 6 cpu cycles

usize::count_trailing_zeros: 9.5 CPU cycles usize::count_ones: 21 CPU cycles

f64::max: about 12? f64::max is not fast due to the fact that it needs to handle NaNs. A simple implementation of max using > is much faster if your data won’t have NaNs.

Vec::clear / ArrayVec::clear: 2

References

Footnotes
  1. Not recommended: Linux only; requires sudo access to set the kernel parameter kernel.perf_event_paranoid.