From ca2fd1ebdf94270efdb319379551de31f41428a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Donny/=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Sun, 19 Jan 2025 22:31:23 +0900 Subject: [PATCH] perf(es/minifier): Make character frequency analysis parallel (#9895) --- .changeset/tall-flowers-remember.md | 6 ++ crates/swc_ecma_minifier/src/util/base54.rs | 106 ++++++++++++++++---- 2 files changed, 90 insertions(+), 22 deletions(-) create mode 100644 .changeset/tall-flowers-remember.md diff --git a/.changeset/tall-flowers-remember.md b/.changeset/tall-flowers-remember.md new file mode 100644 index 000000000000..e94a1170099d --- /dev/null +++ b/.changeset/tall-flowers-remember.md @@ -0,0 +1,6 @@ +--- +swc_core: minor +swc_ecma_minifier: minor +--- + +perf(es/minifier): Make character frequency analysis parallel diff --git a/crates/swc_ecma_minifier/src/util/base54.rs b/crates/swc_ecma_minifier/src/util/base54.rs index 54186dc3eae6..764f02051b85 100644 --- a/crates/swc_ecma_minifier/src/util/base54.rs +++ b/crates/swc_ecma_minifier/src/util/base54.rs @@ -8,6 +8,7 @@ use swc_common::{ }; use swc_ecma_ast::*; use swc_ecma_codegen::{text_writer::WriteJs, Emitter}; +use swc_ecma_utils::parallel::{cpu_count, Parallel, ParallelExt}; use swc_ecma_visit::{noop_visit_type, visit_obj_and_computed, Visit, VisitWith}; #[derive(Clone, Copy)] @@ -226,31 +227,43 @@ impl CharFreq { } pub fn compute(p: &Program, preserved: &FxHashSet, unresolved_ctxt: SyntaxContext) -> Self { - let cm = Lrc::new(DummySourceMap); + let (mut a, b) = swc_parallel::join( + || { + let cm = Lrc::new(DummySourceMap); + let mut freq = Self::default(); + + { + let mut emitter = Emitter { + cfg: swc_ecma_codegen::Config::default() + .with_target(EsVersion::latest()) + .with_minify(true), + cm, + comments: None, + wr: &mut freq, + }; + + emitter.emit_program(p).unwrap(); + } - let mut freq = Self::default(); + freq + }, + || { + let mut visitor = CharFreqAnalyzer { + freq: Default::default(), + preserved, + unresolved_ctxt, + }; - { - let mut emitter = Emitter { - cfg: swc_ecma_codegen::Config::default() - .with_target(EsVersion::latest()) - .with_minify(true), - cm, - comments: None, - wr: &mut freq, - }; - - emitter.emit_program(p).unwrap(); - } + // Subtract + p.visit_with(&mut visitor); - // Subtract - p.visit_with(&mut CharFreqAnalyzer { - freq: &mut freq, - preserved, - unresolved_ctxt, - }); + visitor.freq + }, + ); - freq + a += b; + + a } pub fn compile(self) -> Base54Chars { @@ -290,11 +303,24 @@ impl CharFreq { } struct CharFreqAnalyzer<'a> { - freq: &'a mut CharFreq, + freq: CharFreq, preserved: &'a FxHashSet, unresolved_ctxt: SyntaxContext, } +impl Parallel for CharFreqAnalyzer<'_> { + fn create(&self) -> Self { + Self { + freq: Default::default(), + ..*self + } + } + + fn merge(&mut self, other: Self) { + self.freq += other.freq; + } +} + impl Visit for CharFreqAnalyzer<'_> { noop_visit_type!(); @@ -325,6 +351,42 @@ impl Visit for CharFreqAnalyzer<'_> { /// This is preserved anyway fn visit_module_export_name(&mut self, _: &ModuleExportName) {} + + fn visit_expr_or_spreads(&mut self, n: &[ExprOrSpread]) { + self.maybe_par(cpu_count(), n, |v, n| { + n.visit_with(v); + }); + } + + fn visit_exprs(&mut self, exprs: &[Box]) { + self.maybe_par(cpu_count(), exprs, |v, expr| { + expr.visit_with(v); + }); + } + + fn visit_module_items(&mut self, items: &[ModuleItem]) { + self.maybe_par(cpu_count(), items, |v, item| { + item.visit_with(v); + }); + } + + fn visit_opt_vec_expr_or_spreads(&mut self, n: &[Option]) { + self.maybe_par(cpu_count(), n, |v, n| { + n.visit_with(v); + }); + } + + fn visit_prop_or_spreads(&mut self, n: &[PropOrSpread]) { + self.maybe_par(cpu_count(), n, |v, n| { + n.visit_with(v); + }); + } + + fn visit_stmts(&mut self, stmts: &[Stmt]) { + self.maybe_par(cpu_count(), stmts, |v, stmt| { + stmt.visit_with(v); + }); + } } impl AddAssign for CharFreq {