Skip to content

Commit 2118226

Browse files
authored
[turbopack] Reduce the size of module graph datastructures (#79706)
## Refactor module graph to reduce memory usage ### What? This PR refactors the module graph implementation to reduce memory usage by: 1. Changing `graph_idx` from `usize` to `u32` to reduce memory footprint 2. Removing unused fields from `SingleModuleGraphModuleNode` (layer and issues) 3. Moving layer resolution to the point of use in dynamic imports and server actions This is a small progression in runtime: ![image.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/AwJ29EfoPcPdLSwCZxAz/d669023b-9ac4-44d5-ac9f-54e42b71d341.png) ### Why? These changes optimize memory usage in the module graph, which is particularly important for large applications. By removing unused fields and using more compact types, we can reduce the memory footprint of the graph. Notably, SingleModuleGraphNode is now 24 bytes instead of 48. To make it smaller still we would need to reduce the size of visited moduel, perhaps by storing a reference to the graph that did the original visit? This would be tricky from a lifetimes perspective but much more optimal.
1 parent 6e80e56 commit 2118226

File tree

3 files changed

+83
-131
lines changed

3 files changed

+83
-131
lines changed

crates/next-api/src/dynamic_imports.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -125,12 +125,12 @@ pub async fn map_next_dynamic(graph: Vc<SingleModuleGraph>) -> Result<Vc<Dynamic
125125
.await?
126126
.iter_nodes()
127127
.map(|node| async move {
128-
let SingleModuleGraphModuleNode { module, layer, .. } = node;
129-
130-
if layer
131-
.as_ref()
132-
.is_some_and(|layer| &**layer == "app-client" || &**layer == "client")
133-
{
128+
let SingleModuleGraphModuleNode { module } = node;
129+
let layer = match module.ident().await?.layer {
130+
Some(l) => Some(l.await?),
131+
None => None,
132+
};
133+
if layer.is_some_and(|layer| *layer == "app-client" || *layer == "client") {
134134
if let Some(dynamic_entry_module) =
135135
ResolvedVc::try_downcast_type::<NextDynamicEntryModule>(*module)
136136
{

crates/next-api/src/server_actions.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -435,14 +435,17 @@ pub async fn map_server_actions(graph: Vc<SingleModuleGraph>) -> Result<Vc<AllMo
435435
.iter_nodes()
436436
.map(|node| {
437437
async move {
438-
let SingleModuleGraphModuleNode { module, layer, .. } = node;
439-
438+
let SingleModuleGraphModuleNode { module } = node;
439+
let layer = match module.ident().await?.layer {
440+
Some(l) => Some(l.await?),
441+
None => None,
442+
};
440443
// TODO: compare module contexts instead?
441-
let layer = match &layer {
442-
Some(layer) if &**layer == "app-rsc" || &**layer == "app-edge-rsc" => {
444+
let layer = match layer {
445+
Some(layer) if *layer == "app-rsc" || *layer == "app-edge-rsc" => {
443446
ActionLayer::Rsc
444447
}
445-
Some(layer) if &**layer == "app-client" => ActionLayer::ActionBrowser,
448+
Some(layer) if *layer == "app-client" => ActionLayer::ActionBrowser,
446449
// TODO really ignore SSR?
447450
_ => return Ok(None),
448451
};

0 commit comments

Comments
 (0)