diff --git a/CHANGELOG.md b/CHANGELOG.md index 58269a9..42ebd8d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +### Fixed + +- Make the non-default `html_reports` feature control HTML report generation again. + ## [0.8.2](https://github.com/criterion-rs/criterion.rs/compare/criterion-v0.8.1...criterion-v0.8.2) - 2026-02-04 ### Fixed diff --git a/Cargo.toml b/Cargo.toml index e391984..2cdcb60 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,7 +36,7 @@ exclude = ["book/*"] [dependencies] anes = "0.1.4" -criterion-plot = { path = "plot", version = "0.8.2" } +criterion-plot = { path = "plot", version = "0.8.2", optional = true } itertools = "0.13" page_size = "0.6" serde = { version = "1.0.100", features = ["derive"] } @@ -44,7 +44,7 @@ serde_json = "1.0.100" ciborium = "0.2.0" clap = { version = "4.5", default-features = false, features = ["std", "help"] } walkdir = "2.3" -tinytemplate = "1.1" +tinytemplate = { version = "1.1", optional = true } cast = "0.3" num-traits = { version = "0.2", default-features = false, features = ["std"] } oorandom = "11.1" @@ -106,7 +106,7 @@ async_smol = ["dep:smol", "async"] async_tokio = ["dep:tokio", "async"] # Make Criterion.rs generate its own plots (as opposed to using cargo-criterion) -html_reports = [] +html_reports = ["dep:criterion-plot", "dep:tinytemplate"] # Make Criterion.rs usable outside of cargo-criterion. cargo_bench_support = [] diff --git a/book/src/user_guide/html_report.md b/book/src/user_guide/html_report.md index bc36e40..c392284 100644 --- a/book/src/user_guide/html_report.md +++ b/book/src/user_guide/html_report.md @@ -1,10 +1,12 @@ # HTML Report -Starting with Criterion.rs 0.4.0 HTML reports must be explicitly enabled via the `html_reports` [feature](https://doc.rust-lang.org/cargo/reference/features.html#dependency-features): +HTML reports must be explicitly enabled via the `html_reports` [feature](https://doc.rust-lang.org/cargo/reference/features.html#dependency-features): + ```toml [dev-dependencies] -criterion = { version = "0.5", features = ["html_reports"] } +criterion = { version = "0.8", features = ["html_reports"] } ``` + Criterion.rs can generate an HTML report displaying the results of the benchmark under `target/criterion/reports/index.html`. By default, the plots are generated using [gnuplot](http://www.gnuplot.info/) if it is available, or the diff --git a/book/src/user_guide/plots_and_graphs.md b/book/src/user_guide/plots_and_graphs.md index 3130801..2efdc01 100644 --- a/book/src/user_guide/plots_and_graphs.md +++ b/book/src/user_guide/plots_and_graphs.md @@ -6,12 +6,11 @@ understanding of the behavior of the benchmark. These charts will be generated w it is not available. The examples below were generated using the gnuplot backend, but the plotters ones are similar. -Note that in older versions of criterion.rs html reports were enabled by default. Recent versions -have introduced a cargo feature for plot and html generation. In order to activate the html report -generation make sure that your `Cargo.toml` activates the feature: +HTML reports and plot generation are controlled by the non-default `html_reports` feature. Enable it +in your `Cargo.toml` to generate HTML reports: ```toml -criterion = { version = "0.5", features = ["html_reports"] } +criterion = { version = "0.8", features = ["html_reports"] } ``` ## File Structure diff --git a/src/lib.rs b/src/lib.rs index e0c6610..210423d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -48,10 +48,12 @@ mod error; mod estimate; mod format; mod fs; +#[cfg(feature = "html_reports")] mod html; mod kde; mod macros; pub mod measurement; +#[cfg(feature = "html_reports")] mod plot; pub mod profiler; mod report; @@ -70,19 +72,20 @@ use std::{ time::Duration, }; -use { - criterion_plot::{Version, VersionError}, - std::sync::OnceLock, -}; +#[cfg(feature = "html_reports")] +use criterion_plot::{Version, VersionError}; +use std::sync::OnceLock; -#[cfg(feature = "plotters")] +#[cfg(feature = "html_reports")] +use crate::html::Html; +#[cfg(all(feature = "html_reports", feature = "plotters"))] use crate::plot::PlottersBackend; +#[cfg(feature = "html_reports")] +use crate::plot::{Gnuplot, Plotter}; use crate::{ benchmark::BenchmarkConfig, connection::{Connection, OutgoingMessage}, - html::Html, measurement::{Measurement, WallTime}, - plot::{Gnuplot, Plotter}, profiler::{ExternalProfiler, Profiler}, report::{BencherReport, CliReport, CliVerbosity, Report, ReportContext, Reports}, }; @@ -94,12 +97,14 @@ pub use crate::{ benchmark_group::{BenchmarkGroup, BenchmarkId}, }; +#[cfg(feature = "html_reports")] fn gnuplot_version() -> &'static Result { static GNUPLOT_VERSION: OnceLock> = OnceLock::new(); GNUPLOT_VERSION.get_or_init(criterion_plot::version) } +#[cfg(feature = "html_reports")] fn default_plotting_backend() -> &'static PlottingBackend { static DEFAULT_PLOTTING_BACKEND: OnceLock = OnceLock::new(); @@ -278,6 +283,7 @@ pub enum PlottingBackend { /// Null plotting backend which outputs nothing, None, } +#[cfg(feature = "html_reports")] impl PlottingBackend { fn create_plotter(&self) -> Option> { match self { @@ -405,6 +411,7 @@ impl Default for Criterion { cli: CliReport::new(false, false, CliVerbosity::Normal), bencher_enabled: false, bencher: BencherReport, + #[cfg(feature = "html_reports")] html: default_plotting_backend().create_plotter().map(Html::new), csv_enabled: cfg!(feature = "csv_output"), }; @@ -442,7 +449,10 @@ impl Default for Criterion { criterion.report.cli_enabled = false; criterion.report.bencher_enabled = false; criterion.report.csv_enabled = false; - criterion.report.html = None; + #[cfg(feature = "html_reports")] + { + criterion.report.html = None; + } } criterion } @@ -487,6 +497,7 @@ impl Criterion { /// Panics if `backend` is [`PlottingBackend::Gnuplot`] and `gnuplot` is not available. /// /// [plotting backend]: PlottingBackend + #[cfg(feature = "html_reports")] pub fn plotting_backend(mut self, backend: PlottingBackend) -> Criterion { if let PlottingBackend::Gnuplot = backend { assert!( @@ -501,6 +512,16 @@ impl Criterion { self } + #[must_use] + /// Set the plotting backend. + /// + /// This has no effect when Criterion.rs is built without the `html_reports` feature. + #[cfg(not(feature = "html_reports"))] + pub fn plotting_backend(self, backend: PlottingBackend) -> Criterion { + let _ = backend; + self + } + #[must_use] /// Changes the default size of the sample for benchmarks run with this runner. /// @@ -641,6 +662,7 @@ impl Criterion { #[must_use] /// Enables plotting + #[cfg(feature = "html_reports")] pub fn with_plots(mut self) -> Criterion { // If running under cargo-criterion then don't re-enable the reports; let it do the reporting. if self.connection.is_none() && self.report.html.is_none() { @@ -654,13 +676,32 @@ impl Criterion { self } + #[must_use] + /// Enables plotting. + /// + /// This has no effect when Criterion.rs is built without the `html_reports` feature. + #[cfg(not(feature = "html_reports"))] + pub fn with_plots(self) -> Criterion { + self + } + #[must_use] /// Disables plotting + #[cfg(feature = "html_reports")] pub fn without_plots(mut self) -> Criterion { self.report.html = None; self } + #[must_use] + /// Disables plotting. + /// + /// This has no effect when Criterion.rs is built without the `html_reports` feature. + #[cfg(not(feature = "html_reports"))] + pub fn without_plots(self) -> Criterion { + self + } + #[must_use] /// Names an explicit baseline and enables overwriting the previous results. pub fn save_baseline(mut self, baseline: String) -> Criterion { @@ -1057,7 +1098,10 @@ https://criterion-rs.github.io/book/faq.html self.report.cli_enabled = false; self.report.bencher_enabled = false; self.report.csv_enabled = false; - self.report.html = None; + #[cfg(feature = "html_reports")] + { + self.report.html = None; + } } else { match matches.get_one("output-format").map(String::as_str) { Some("bencher") => { diff --git a/src/report.rs b/src/report.rs index 2cb15ce..2249185 100644 --- a/src/report.rs +++ b/src/report.rs @@ -1,8 +1,10 @@ #[cfg(feature = "csv_output")] use crate::csv_report::FileCsvReport; +#[cfg(feature = "html_reports")] +use crate::html::Html; use crate::stats::bivariate::regression::Slope; +use crate::stats::bivariate::Data; use crate::stats::univariate::outliers::tukey::LabeledSample; -use crate::{html::Html, stats::bivariate::Data}; use crate::estimate::{ChangeDistributions, ChangeEstimates, Distributions, Estimate, Estimates}; use crate::format; @@ -319,6 +321,7 @@ pub(crate) struct Reports { pub(crate) bencher_enabled: bool, pub(crate) bencher: BencherReport, pub(crate) csv_enabled: bool, + #[cfg(feature = "html_reports")] pub(crate) html: Option, } macro_rules! reports_impl { @@ -334,6 +337,7 @@ macro_rules! reports_impl { if self.csv_enabled { FileCsvReport.$name($($argn),*); } + #[cfg(feature = "html_reports")] if let Some(reporter) = &self.html { reporter.$name($($argn),*); } diff --git a/tests/criterion_tests.rs b/tests/criterion_tests.rs index 8c6d6f7..1b0b62f 100644 --- a/tests/criterion_tests.rs +++ b/tests/criterion_tests.rs @@ -137,6 +137,18 @@ fn test_without_plots() { } } +#[cfg(all(feature = "plotters", not(feature = "html_reports")))] +#[test] +fn test_plotters_without_html_reports_does_not_generate_report() { + let dir = temp_dir(); + short_benchmark(&dir).bench_function("test_html_reports_disabled", |b| b.iter(|| 10)); + + let benchmark_dir = dir.path().join("test_html_reports_disabled"); + verify_stats(&benchmark_dir, "new"); + verify_stats(&benchmark_dir, "base"); + verify_not_exists(&benchmark_dir, "report"); +} + #[test] fn test_save_baseline() { let dir = temp_dir();