How is it possible to benchmark programs in Rust? For example, how would I get execution time of program in seconds?
相关问题
- Share Arc between closures
- How to account for clock offsets in a distributed
- Function references: expected bound lifetime param
- Pattern matching on slices
- How can I iteratively call Sha256::digest, passing
相关文章
- How can I convert a f64 to f32 and get the closest
- What is a good way of cleaning up after a unit tes
- How can I unpack (destructure) elements from a vec
- How to import macros in Rust?
- Get POSIX epoch as system_clock::time_point
- How to get struct field names in Rust? [duplicate]
- Confusion between [T] and &[T]
- How do I initialize an opaque C struct when using
You might try timing individual components within the program using the time crate.
If you simply want to time a piece of code, you can use the
time
crate. time meanwhile deprecated, though. A follow-up crate ischrono
.Add
time = "*"
to yourCargo.toml
.Add
before your main function and
Complete example
Cargo.toml
rust.rs
For measuring time without adding 3rd party dependencies you can use
std::time::Instant
Currently, there is no interface to any of the following Linux functions:
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts)
getrusage
times
(manpage:man 2 times
)The available ways to measure the CPU time and hotspots of a Rust program on Linux are:
/usr/bin/time program
perf stat program
perf record --freq 100000 program; perf report
valgrind --tool=callgrind program; kcachegrind callgrind.out.*
The output of
perf report
andvalgrind
depends on the availability of debugging information in the program. It may not work.There are several ways to benchmark your Rust program. For most real benchmarks, you should use a proper benchmarking framework as they help with a couple of things that are easy to screw up (including statistical analysis). Please also read the "Why writing benchmarks is hard" section at the very bottom!
Quick and easy:
Instant
andDuration
from the standard libraryTo quickly check how long a piece of code runs, you can use the types in
std::time
. The module is fairly minimal, but it is fine for simple time measurements. You should useInstant
instead ofSystemTime
as the former is a monotonically increasing clock and the latter is not. Example (Playground):The precision of std's
Instant
is unfortunately not specified in the documentation, but on all major operating systems it uses the best precision that the platform can provide (this is typically approximately around 20ns).If
std::time
does not offer enough features for your case, you could take a look atchrono
. However, for measuring durations, it's unlikely you need that external crate.Using a benchmarking framework
Using frameworks is often a good idea, because they try to prevent you from doing specific mistakes.
Rust's built-in benchmarking framework (nightly only)
Rust has a convenient built-in benchmarking feature, which is unfortunately still unstable as of 2019-07. You have to add the
#[bench]
attribute to your function and make it accept one&mut test::Bencher
argument:Executing
cargo bench
will print:Criterion
The crate
criterion
is a framework that runs on stable, but it is a bit more complicated than the built-in solution. It does more sophisticated statistical analysis, offers a richer API, produces more information and can even automatically generate plots.See the "Quickstart" section for more information on how to use Criterion.
Why writing benchmarks is hard
There are many pitfalls when writing benchmarks. A single mistake can make your benchmark results meaningless. Here is a list of common mistakes:
rustc -O3
orcargo build --release
. When you are executing your benchmarks withcargo bench
, Cargo will automatically enabled optimizations. This step is important as there are often large performance difference between optimized and unoptimized Rust code.Make sure your benchmark isn't completely removed: benchmarks are very artificial by nature. Usually, the result of your workload is not inspected as you only want to measure the duration. However, this means that a good optimizer could remove your whole benchmark because it does not have side-effects (well, apart from the passage of time). So to trick the optimizer you have to somehow use your result value so that your workload cannot be removed. An easy way is to print the result. A better solution is something like
black_box
. This function basically hides a value from LLVM in that LLVM cannot know what will happen with the value. Nothing happens, but LLVM doesn't know. That is the point.Good benchmarking frameworks use a block box in several situations. For example, the closure given to the
iter
method (for both, the built-in and CriterionBencher
) can return a value. That value is automatically passed into ablack_box
.black_box
to avoid LLVM optimizing too aggressively.It might be worth noting 2 years later (to help any future Rust programmers who stumble on this page) that there are now tools to benchmark Rust code as a part of one's test suite.
(From the guide link below) Using the
#[bench]
attribute, one can use the standard Rust tooling to benchmark methods in their code.For the command
cargo bench
this outputs something like:Links:
test
crate)