Skip to content

Commit 7759ea3

Browse files
kdy1sokra
andauthored
perf(turbopack): Use last side effect as ModuleEvaluation fragment (#76940)
### What? Use the last side effect fragment instead of the module evaluation fragment. ### Why? Module evaluation fragment is a waste of memory. ### How? Closes PACK-3440 --------- Co-authored-by: Tobias Koppers <[email protected]>
1 parent 3755415 commit 7759ea3

File tree

82 files changed

+4058
-3694
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+4058
-3694
lines changed

Diff for: turbopack/crates/turbopack-ecmascript/src/tree_shake/asset.rs

-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@ impl EcmascriptModulePartAsset {
101101
| ModulePart::InternalEvaluation(..)
102102
| ModulePart::Facade
103103
| ModulePart::Exports
104-
| ModulePart::Evaluation
105104
) {
106105
return Ok(EcmascriptModulePartAsset {
107106
full_module: module,

Diff for: turbopack/crates/turbopack-ecmascript/src/tree_shake/graph.rs

+44-23
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ pub(crate) enum ItemId {
4444

4545
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
4646
pub(crate) enum ItemIdGroupKind {
47+
/// Used only for testing
48+
#[cfg(test)]
4749
ModuleEvaluation,
4850
/// `(local, export_name)``
4951
Export(Id, Atom),
@@ -130,6 +132,8 @@ pub(crate) struct ItemData {
130132

131133
/// Server actions breaks when we merge exports.
132134
pub disable_export_merging: bool,
135+
136+
pub is_module_evaluation: bool,
133137
}
134138

135139
impl fmt::Debug for ItemData {
@@ -145,6 +149,8 @@ impl fmt::Debug for ItemData {
145149
.field("side_effects", &self.side_effects)
146150
.field("export", &self.export)
147151
.field("explicit_deps", &self.explicit_deps)
152+
.field("disable_export_merging", &self.disable_export_merging)
153+
.field("is_module_evaluation", &self.is_module_evaluation)
148154
.finish()
149155
}
150156
}
@@ -165,6 +171,7 @@ impl Default for ItemData {
165171
binding_source: Default::default(),
166172
explicit_deps: Default::default(),
167173
disable_export_merging: Default::default(),
174+
is_module_evaluation: Default::default(),
168175
}
169176
}
170177
}
@@ -328,6 +335,8 @@ impl DepGraph {
328335
.clone()
329336
};
330337

338+
let mut module_evaluation_ix = None;
339+
331340
for (ix, group) in groups.graph_ix.iter().enumerate() {
332341
let mut chunk = Module {
333342
span: DUMMY_SP,
@@ -389,10 +398,10 @@ impl DepGraph {
389398
}
390399
}
391400

392-
for item in group {
393-
match item {
401+
for item_id in group {
402+
match item_id {
394403
ItemId::Group(ItemIdGroupKind::Export(..)) => {
395-
if let Some(export) = &data[item].export {
404+
if let Some(export) = &data[item_id].export {
396405
outputs.insert(Key::Export(export.as_str().into()), ix as u32);
397406

398407
let s = ExportSpecifier::Named(ExportNamedSpecifier {
@@ -418,11 +427,14 @@ impl DepGraph {
418427
));
419428
}
420429
}
421-
ItemId::Group(ItemIdGroupKind::ModuleEvaluation) => {
422-
outputs.insert(Key::ModuleEvaluation, ix as u32);
423-
}
424430

425-
_ => {}
431+
_ => {
432+
if data[item_id].is_module_evaluation {
433+
debug_assert_eq!(module_evaluation_ix, None);
434+
module_evaluation_ix = Some(ix as u32);
435+
outputs.insert(Key::ModuleEvaluation, ix as u32);
436+
}
437+
}
426438
}
427439
}
428440

@@ -686,6 +698,31 @@ impl DepGraph {
686698

687699
modules.push(exports_module);
688700

701+
// Currently we need to have `Key::ModuleEvaluation` in the outputs
702+
// even if it is empty.
703+
if module_evaluation_ix.is_none() {
704+
outputs.insert(Key::ModuleEvaluation, modules.len() as u32);
705+
module_evaluation_ix = Some(modules.len() as u32);
706+
modules.push(Module {
707+
span: DUMMY_SP,
708+
body: vec![],
709+
shebang: None,
710+
});
711+
}
712+
713+
// Push `export {}` to the module evaluation to make it module.
714+
modules[module_evaluation_ix.unwrap() as usize]
715+
.body
716+
.push(ModuleItem::ModuleDecl(ModuleDecl::ExportNamed(
717+
NamedExport {
718+
span: DUMMY_SP,
719+
specifiers: Default::default(),
720+
src: None,
721+
type_only: false,
722+
with: None,
723+
},
724+
)));
725+
689726
SplitModuleResult {
690727
entrypoints: outputs,
691728
part_deps,
@@ -1370,22 +1407,6 @@ impl DepGraph {
13701407
}
13711408
}
13721409

1373-
{
1374-
// `module evaluation side effects` Node
1375-
let id = ItemId::Group(ItemIdGroupKind::ModuleEvaluation);
1376-
ids.push(id.clone());
1377-
items.insert(
1378-
id,
1379-
ItemData {
1380-
content: ModuleItem::Stmt(Stmt::Expr(ExprStmt {
1381-
span: DUMMY_SP,
1382-
expr: "module evaluation".into(),
1383-
})),
1384-
..Default::default()
1385-
},
1386-
);
1387-
}
1388-
13891410
for (local, export_name, disable_export_merging) in exports {
13901411
let id = ItemId::Group(ItemIdGroupKind::Export(local.clone(), export_name.clone()));
13911412
ids.push(id.clone());

Diff for: turbopack/crates/turbopack-ecmascript/src/tree_shake/mod.rs

+11-14
Original file line numberDiff line numberDiff line change
@@ -350,23 +350,20 @@ impl Analyzer<'_> {
350350

351351
/// Phase 4: Exports
352352
fn handle_exports(&mut self, _module: &Module) {
353-
for item_id in self.item_ids.iter() {
354-
if let ItemId::Group(kind) = item_id {
355-
match kind {
356-
ItemIdGroupKind::ModuleEvaluation => {
357-
// Create a strong dependency to LAST_SIDE_EFFECTS
353+
// We use the last side effect as a module evaluation
354+
if let Some(last) = self.last_side_effects.last() {
355+
if let Some(item) = self.items.get_mut(last) {
356+
item.is_module_evaluation = true;
357+
}
358+
}
358359

359-
self.g
360-
.add_strong_deps(item_id, self.last_side_effects.last());
361-
}
362-
ItemIdGroupKind::Export(local, _) => {
363-
// Create a strong dependency to LAST_WRITES for this var
360+
for item_id in self.item_ids.iter() {
361+
if let ItemId::Group(ItemIdGroupKind::Export(local, _)) = item_id {
362+
// Create a strong dependency to LAST_WRITES for this var
364363

365-
let state = self.vars.entry(local.clone()).or_default();
364+
let state = self.vars.entry(local.clone()).or_default();
366365

367-
self.g.add_strong_deps(item_id, state.last_writes.iter());
368-
}
369-
}
366+
self.g.add_strong_deps(item_id, state.last_writes.iter());
370367
}
371368
}
372369
}

0 commit comments

Comments
 (0)