diff --git a/crates/biome_html_analyze/benches/fixtures/real b/crates/biome_html_analyze/benches/fixtures/real
new file mode 120000
index 000000000000..555b3306a001
--- /dev/null
+++ b/crates/biome_html_analyze/benches/fixtures/real
@@ -0,0 +1 @@
+../../../biome_html_parser/benches/fixtures/real
\ No newline at end of file
diff --git a/crates/biome_html_analyze/benches/html_analyzer.rs b/crates/biome_html_analyze/benches/html_analyzer.rs
index 0215a2f6ebbf..06e930e77717 100644
--- a/crates/biome_html_analyze/benches/html_analyzer.rs
+++ b/crates/biome_html_analyze/benches/html_analyzer.rs
@@ -1,3 +1,5 @@
+use std::{collections::HashMap, fs, path::Path};
+
use biome_analyze::options::JsxRuntime;
use biome_analyze::{
AnalysisFilter, AnalyzerConfiguration, AnalyzerOptions, ControlFlow, Never,
@@ -6,8 +8,7 @@ use biome_analyze::{
use biome_html_parser::{HtmlParserOptions, parse_html};
use biome_html_syntax::HtmlFileSource;
use biome_test_utils::BenchCase;
-use criterion::{BenchmarkId, Criterion, black_box, criterion_group, criterion_main};
-use std::collections::HashMap;
+use criterion::{BenchmarkId, Criterion, Throughput, black_box, criterion_group, criterion_main};
#[cfg(target_os = "windows")]
#[global_allocator]
@@ -24,11 +25,58 @@ static GLOBAL: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;
#[cfg(all(target_env = "musl", target_os = "linux", target_arch = "aarch64"))]
#[global_allocator]
static GLOBAL: std::alloc::System = std::alloc::System;
+
+fn load_fixtures() -> Result, std::io::Error> {
+ let fixtures_root = Path::new(env!("CARGO_MANIFEST_DIR")).join("benches/fixtures");
+ let mut cases = Vec::new();
+
+ fn visit(
+ dir: &Path,
+ root: &Path,
+ cases: &mut Vec<(String, String, String)>,
+ ) -> Result<(), std::io::Error> {
+ for entry in fs::read_dir(dir)? {
+ let entry = entry?;
+ let path = entry.path();
+ if path.is_dir() {
+ visit(&path, root, cases)?;
+ } else if path.is_file() {
+ if matches!(path.extension().and_then(|e| e.to_str()), Some(ext) if ext.eq_ignore_ascii_case("md"))
+ {
+ continue;
+ }
+
+ let rel = path.strip_prefix(root).unwrap_or(&path);
+ let group = rel
+ .iter()
+ .next()
+ .and_then(|segment| segment.to_str())
+ .unwrap_or("root")
+ .to_string();
+ let name = path
+ .file_name()
+ .and_then(|segment| segment.to_str())
+ .unwrap_or_default()
+ .to_string();
+ let content = fs::read_to_string(&path)?;
+
+ cases.push((group, name, content));
+ }
+ }
+
+ Ok(())
+ }
+
+ visit(&fixtures_root, &fixtures_root, &mut cases)?;
+ Ok(cases)
+}
+
fn bench_analyzer(criterion: &mut Criterion) {
let mut all_suites = HashMap::new();
all_suites.insert("html", include_str!("libs-html.txt"));
let mut libs = vec![];
libs.extend(all_suites.values().flat_map(|suite| suite.lines()));
+ let fixtures = load_fixtures().expect("failed to load fixtures");
let mut group = criterion.benchmark_group("html_analyzer");
@@ -38,14 +86,16 @@ fn bench_analyzer(criterion: &mut Criterion) {
match test_case {
Ok(test_case) => {
let code = test_case.code();
- let file_source = HtmlFileSource::html();
- group.throughput(criterion::Throughput::Bytes(code.len() as u64));
+ let file_source = HtmlFileSource::try_from(test_case.path()).unwrap_or_else(|_| {
+ panic!("failed to determine file source for {}", test_case.path())
+ });
+ let parse = parse_html(code, HtmlParserOptions::from(&file_source));
+
+ group.throughput(Throughput::Bytes(code.len() as u64));
group.bench_with_input(
BenchmarkId::from_parameter(test_case.filename()),
code,
|b, _| {
- let parse = parse_html(code, HtmlParserOptions::from(&file_source));
-
let filter = AnalysisFilter {
categories: RuleCategoriesBuilder::default()
.with_syntax()
@@ -54,10 +104,8 @@ fn bench_analyzer(criterion: &mut Criterion) {
.build(),
..AnalysisFilter::default()
};
- let options = AnalyzerOptions::default().with_configuration(
- AnalyzerConfiguration::default()
- .with_jsx_runtime(JsxRuntime::default()),
- );
+ let options = AnalyzerOptions::default()
+ .with_configuration(AnalyzerConfiguration::default());
b.iter(|| {
biome_html_analyze::analyze(
@@ -79,6 +127,45 @@ fn bench_analyzer(criterion: &mut Criterion) {
}
}
+ for (group_name, name, content) in fixtures {
+ let code = content.as_str();
+ let ext = name.rsplit('.').next().unwrap_or_default();
+ let file_source = HtmlFileSource::try_from_extension(ext).unwrap_or_else(|_| {
+ panic!("failed to determine file source for fixture {group_name}/{name}")
+ });
+ let parse = parse_html(code, HtmlParserOptions::from(&file_source));
+ let id = format!("{group_name}/{name}");
+
+ group.throughput(Throughput::Bytes(code.len() as u64));
+ group.bench_with_input(BenchmarkId::from_parameter(&id), code, |b, _| {
+ let filter = AnalysisFilter {
+ categories: RuleCategoriesBuilder::default()
+ .with_syntax()
+ .with_lint()
+ .with_assist()
+ .build(),
+ ..AnalysisFilter::default()
+ };
+ let options = AnalyzerOptions::default().with_configuration(
+ AnalyzerConfiguration::default().with_jsx_runtime(JsxRuntime::default()),
+ );
+
+ b.iter(|| {
+ biome_html_analyze::analyze(
+ &parse.tree(),
+ filter,
+ &options,
+ file_source,
+ |event| {
+ black_box(event.diagnostic());
+ black_box(event.actions());
+ ControlFlow::::Continue(())
+ },
+ );
+ });
+ });
+ }
+
group.finish();
}