Skip to content

Commit ca2fd1e

Browse files
authoredJan 19, 2025··
perf(es/minifier): Make character frequency analysis parallel (#9895)
1 parent 9962c9c commit ca2fd1e

File tree

2 files changed

+90
-22
lines changed

2 files changed

+90
-22
lines changed
 

‎.changeset/tall-flowers-remember.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
swc_core: minor
3+
swc_ecma_minifier: minor
4+
---
5+
6+
perf(es/minifier): Make character frequency analysis parallel

‎crates/swc_ecma_minifier/src/util/base54.rs

+84-22
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use swc_common::{
88
};
99
use swc_ecma_ast::*;
1010
use swc_ecma_codegen::{text_writer::WriteJs, Emitter};
11+
use swc_ecma_utils::parallel::{cpu_count, Parallel, ParallelExt};
1112
use swc_ecma_visit::{noop_visit_type, visit_obj_and_computed, Visit, VisitWith};
1213

1314
#[derive(Clone, Copy)]
@@ -226,31 +227,43 @@ impl CharFreq {
226227
}
227228

228229
pub fn compute(p: &Program, preserved: &FxHashSet<Id>, unresolved_ctxt: SyntaxContext) -> Self {
229-
let cm = Lrc::new(DummySourceMap);
230+
let (mut a, b) = swc_parallel::join(
231+
|| {
232+
let cm = Lrc::new(DummySourceMap);
233+
let mut freq = Self::default();
234+
235+
{
236+
let mut emitter = Emitter {
237+
cfg: swc_ecma_codegen::Config::default()
238+
.with_target(EsVersion::latest())
239+
.with_minify(true),
240+
cm,
241+
comments: None,
242+
wr: &mut freq,
243+
};
244+
245+
emitter.emit_program(p).unwrap();
246+
}
230247

231-
let mut freq = Self::default();
248+
freq
249+
},
250+
|| {
251+
let mut visitor = CharFreqAnalyzer {
252+
freq: Default::default(),
253+
preserved,
254+
unresolved_ctxt,
255+
};
232256

233-
{
234-
let mut emitter = Emitter {
235-
cfg: swc_ecma_codegen::Config::default()
236-
.with_target(EsVersion::latest())
237-
.with_minify(true),
238-
cm,
239-
comments: None,
240-
wr: &mut freq,
241-
};
242-
243-
emitter.emit_program(p).unwrap();
244-
}
257+
// Subtract
258+
p.visit_with(&mut visitor);
245259

246-
// Subtract
247-
p.visit_with(&mut CharFreqAnalyzer {
248-
freq: &mut freq,
249-
preserved,
250-
unresolved_ctxt,
251-
});
260+
visitor.freq
261+
},
262+
);
252263

253-
freq
264+
a += b;
265+
266+
a
254267
}
255268

256269
pub fn compile(self) -> Base54Chars {
@@ -290,11 +303,24 @@ impl CharFreq {
290303
}
291304

292305
struct CharFreqAnalyzer<'a> {
293-
freq: &'a mut CharFreq,
306+
freq: CharFreq,
294307
preserved: &'a FxHashSet<Id>,
295308
unresolved_ctxt: SyntaxContext,
296309
}
297310

311+
impl Parallel for CharFreqAnalyzer<'_> {
312+
fn create(&self) -> Self {
313+
Self {
314+
freq: Default::default(),
315+
..*self
316+
}
317+
}
318+
319+
fn merge(&mut self, other: Self) {
320+
self.freq += other.freq;
321+
}
322+
}
323+
298324
impl Visit for CharFreqAnalyzer<'_> {
299325
noop_visit_type!();
300326

@@ -325,6 +351,42 @@ impl Visit for CharFreqAnalyzer<'_> {
325351

326352
/// This is preserved anyway
327353
fn visit_module_export_name(&mut self, _: &ModuleExportName) {}
354+
355+
fn visit_expr_or_spreads(&mut self, n: &[ExprOrSpread]) {
356+
self.maybe_par(cpu_count(), n, |v, n| {
357+
n.visit_with(v);
358+
});
359+
}
360+
361+
fn visit_exprs(&mut self, exprs: &[Box<Expr>]) {
362+
self.maybe_par(cpu_count(), exprs, |v, expr| {
363+
expr.visit_with(v);
364+
});
365+
}
366+
367+
fn visit_module_items(&mut self, items: &[ModuleItem]) {
368+
self.maybe_par(cpu_count(), items, |v, item| {
369+
item.visit_with(v);
370+
});
371+
}
372+
373+
fn visit_opt_vec_expr_or_spreads(&mut self, n: &[Option<ExprOrSpread>]) {
374+
self.maybe_par(cpu_count(), n, |v, n| {
375+
n.visit_with(v);
376+
});
377+
}
378+
379+
fn visit_prop_or_spreads(&mut self, n: &[PropOrSpread]) {
380+
self.maybe_par(cpu_count(), n, |v, n| {
381+
n.visit_with(v);
382+
});
383+
}
384+
385+
fn visit_stmts(&mut self, stmts: &[Stmt]) {
386+
self.maybe_par(cpu_count(), stmts, |v, stmt| {
387+
stmt.visit_with(v);
388+
});
389+
}
328390
}
329391

330392
impl AddAssign for CharFreq {

0 commit comments

Comments
 (0)
Please sign in to comment.