From 734ec2197f1baf73af0f3d1003595017b06a389b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Donny/=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Fri, 3 Jan 2025 19:44:31 +0900 Subject: [PATCH] perf(es/lints): Configure a benchmark for ES lints (#9833) **Description:** The lints are causing perf issues for turbopack. --- Cargo.lock | 7 ++ crates/swc_ecma_lints/Cargo.toml | 20 ++++- crates/swc_ecma_lints/benches/all.rs | 109 +++++++++++++++++++++++++++ 3 files changed, 132 insertions(+), 4 deletions(-) create mode 100644 crates/swc_ecma_lints/benches/all.rs diff --git a/Cargo.lock b/Cargo.lock index a247c552511c..9f8642f88ad6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5107,9 +5107,13 @@ dependencies = [ name = "swc_ecma_lints" version = "6.0.0" dependencies = [ + "anyhow", "auto_impl", + "codspeed-criterion-compat", + "criterion", "dashmap 5.5.3", "parking_lot", + "pretty_assertions", "rayon", "regex", "serde", @@ -5119,10 +5123,13 @@ dependencies = [ "swc_ecma_ast", "swc_ecma_codegen", "swc_ecma_parser", + "swc_ecma_testing", "swc_ecma_transforms_base", "swc_ecma_utils", "swc_ecma_visit", + "swc_malloc", "testing", + "walkdir", ] [[package]] diff --git a/crates/swc_ecma_lints/Cargo.toml b/crates/swc_ecma_lints/Cargo.toml index 811e86acbb5f..7d0423dc04df 100644 --- a/crates/swc_ecma_lints/Cargo.toml +++ b/crates/swc_ecma_lints/Cargo.toml @@ -32,10 +32,22 @@ swc_ecma_utils = { version = "6.0.0", path = "../swc_ecma_utils" } swc_ecma_visit = { version = "5.0.0", path = "../swc_ecma_visit" } [dev-dependencies] -swc_ecma_codegen = { version = "5.0.1", path = "../swc_ecma_codegen" } -swc_ecma_parser = { version = "6.0.1", path = "../swc_ecma_parser" } -swc_ecma_transforms_base = { version = "6.0.2", path = "../swc_ecma_transforms_base" } -testing = { version = "5.0.0", path = "../testing" } +anyhow = { workspace = true } +codspeed-criterion-compat = { workspace = true } +criterion = { workspace = true } +pretty_assertions = { workspace = true } +swc_ecma_codegen = { version = "5.0.1", path = "../swc_ecma_codegen" } +swc_ecma_parser = { version = "6.0.1", path = "../swc_ecma_parser" } +swc_ecma_testing = { version = "5.0.0", path = "../swc_ecma_testing" } +swc_ecma_transforms_base = { version = "6.0.2", path = "../swc_ecma_transforms_base" } +swc_malloc = { version = "1.0.0", path = "../swc_malloc" } +testing = { version = "5.0.0", path = "../testing" } +walkdir = { workspace = true } [features] non_critical_lints = [] + + +[[bench]] +harness = false +name = "all" diff --git a/crates/swc_ecma_lints/benches/all.rs b/crates/swc_ecma_lints/benches/all.rs new file mode 100644 index 000000000000..09f56f54b777 --- /dev/null +++ b/crates/swc_ecma_lints/benches/all.rs @@ -0,0 +1,109 @@ +extern crate swc_malloc; + +use std::fs::read_to_string; + +use codspeed_criterion_compat::{black_box, criterion_group, criterion_main, Criterion}; +use swc_common::{ + errors::{Handler, HANDLER}, + sync::Lrc, + FileName, Globals, Mark, SourceMap, SyntaxContext, GLOBALS, +}; +use swc_ecma_ast::{EsVersion, Program}; +use swc_ecma_lints::{config::LintConfig, rule::Rule, rules::LintParams}; +use swc_ecma_parser::parse_file_as_module; +use swc_ecma_transforms_base::resolver; +use swc_ecma_visit::{Visit, VisitWith}; + +pub fn bench_files(c: &mut Criterion) { + let mut group = c.benchmark_group("es/lints/libs"); + group.sample_size(10); + + let mut bench_file = |name: &str| { + group.bench_function(format!("es/lints/libs/{}", name), |b| { + let src = + read_to_string(format!("../swc_ecma_minifier/benches/full/{}.js", name)).unwrap(); + + let globals = Globals::default(); + GLOBALS.set(&globals, || { + let cm = Lrc::new(SourceMap::default()); + let handler = Handler::with_tty_emitter( + swc_common::errors::ColorConfig::Always, + true, + false, + Some(cm.clone()), + ); + + let fm = cm.new_source_file(FileName::Anon.into(), src); + + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + let program = parse_file_as_module( + &fm, + Default::default(), + Default::default(), + None, + &mut Vec::new(), + ) + .map_err(|err| { + err.into_diagnostic(&handler).emit(); + }) + .map(Program::Module) + .map(|module| module.apply(resolver(unresolved_mark, top_level_mark, false))) + .unwrap(); + + b.iter(|| { + GLOBALS.set(&globals, || { + HANDLER.set(&handler, || { + run(cm.clone(), program.clone(), unresolved_mark, top_level_mark) + }); + }); + }); + }); + }); + }; + + bench_file("antd"); + bench_file("d3"); + bench_file("echarts"); + bench_file("jquery"); + bench_file("lodash"); + bench_file("moment"); + bench_file("react"); + bench_file("terser"); + bench_file("three"); + bench_file("typescript"); + bench_file("victory"); + bench_file("vue"); +} + +criterion_group!(files, bench_files); +criterion_main!(files); + +fn run(cm: Lrc, program: Program, unresolved_mark: Mark, top_level_mark: Mark) { + let rules = swc_ecma_lints::rules::all(LintParams { + program: &program, + lint_config: &LintConfig::default(), + unresolved_ctxt: SyntaxContext::empty().apply_mark(unresolved_mark), + top_level_ctxt: SyntaxContext::empty().apply_mark(top_level_mark), + es_version: EsVersion::EsNext, + source_map: cm.clone(), + }); + + let mut visitor = black_box(Visitors(rules)); + + program.visit_with(&mut visitor); +} + +struct Visitors(Vec>); + +impl Visit for Visitors { + fn visit_program(&mut self, program: &Program) { + for rule in self.0.iter_mut() { + match program { + Program::Module(module) => rule.lint_module(module), + Program::Script(script) => rule.lint_script(script), + } + } + } +}