Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/biome_html_analyze/benches/fixtures/real
107 changes: 97 additions & 10 deletions crates/biome_html_analyze/benches/html_analyzer.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::{collections::HashMap, fs, path::Path};

use biome_analyze::options::JsxRuntime;
use biome_analyze::{
AnalysisFilter, AnalyzerConfiguration, AnalyzerOptions, ControlFlow, Never,
Expand All @@ -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]
Expand All @@ -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<Vec<(String, String, String)>, 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");

Expand All @@ -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()
Expand All @@ -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(
Expand All @@ -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()),
Comment thread
dyc3 marked this conversation as resolved.
);

b.iter(|| {
biome_html_analyze::analyze(
&parse.tree(),
filter,
&options,
file_source,
|event| {
black_box(event.diagnostic());
black_box(event.actions());
ControlFlow::<Never>::Continue(())
},
);
});
});
}

group.finish();
}

Expand Down