Skip to content

Commit

Permalink
perf(es/minifier): Make character frequency analysis parallel (#9895)
Browse files Browse the repository at this point in the history
  • Loading branch information
kdy1 authored Jan 19, 2025
1 parent 9962c9c commit ca2fd1e
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 22 deletions.
6 changes: 6 additions & 0 deletions .changeset/tall-flowers-remember.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
swc_core: minor
swc_ecma_minifier: minor
---

perf(es/minifier): Make character frequency analysis parallel
106 changes: 84 additions & 22 deletions crates/swc_ecma_minifier/src/util/base54.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -226,31 +227,43 @@ impl CharFreq {
}

pub fn compute(p: &Program, preserved: &FxHashSet<Id>, 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 {
Expand Down Expand Up @@ -290,11 +303,24 @@ impl CharFreq {
}

struct CharFreqAnalyzer<'a> {
freq: &'a mut CharFreq,
freq: CharFreq,
preserved: &'a FxHashSet<Id>,
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!();

Expand Down Expand Up @@ -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<Expr>]) {
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<ExprOrSpread>]) {
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 {
Expand Down

0 comments on commit ca2fd1e

Please sign in to comment.