From ffd46f01b5985f8ae16dd36ab4faffc4a262741c Mon Sep 17 00:00:00 2001 From: Fy <1114550440@qq.com> Date: Mon, 25 Mar 2024 18:43:25 +0800 Subject: [PATCH] fix: stablize chunk id (#6021) --- .../rspack_core/src/utils/find_graph_roots.rs | 68 ++++++++++--------- crates/rspack_ids/src/id_helpers.rs | 15 +++- 2 files changed, 48 insertions(+), 35 deletions(-) diff --git a/crates/rspack_core/src/utils/find_graph_roots.rs b/crates/rspack_core/src/utils/find_graph_roots.rs index 64c21aacd3e..a62b279feb9 100644 --- a/crates/rspack_core/src/utils/find_graph_roots.rs +++ b/crates/rspack_core/src/utils/find_graph_roots.rs @@ -37,7 +37,7 @@ impl DatabaseItem for Cycle { struct Node { pub ukey: Ukey>, pub item: T, - pub dependencies: FxHashSet>>, + pub dependencies: Vec>>, pub marker: Marker, pub cycle: Option>>>>, pub incoming: usize, @@ -67,7 +67,9 @@ struct StackEntry { open_edges: Vec, } -pub fn find_graph_roots( +pub fn find_graph_roots< + Item: Clone + std::fmt::Debug + PartialEq + Eq + Hash + Send + Sync + Ord + 'static, +>( items: Vec, get_dependencies: impl Sync + Fn(Item) -> Vec, ) -> Vec { @@ -98,7 +100,7 @@ pub fn find_graph_roots>(); }); // Set of current root modules @@ -110,8 +112,11 @@ pub fn find_graph_roots>>>> = FxHashSet::default(); + let mut keys = db.keys().cloned().collect::>(); + keys.sort_by(|a, b| a.as_ref(&db).item.cmp(&b.as_ref(&db).item)); + // For all non-marked nodes - for select_node in db.keys().cloned().collect::>() { + for select_node in keys { if matches!(select_node.as_ref(&db).marker, Marker::NoMarker) { // deep-walk all referenced modules // in a non-recursive way @@ -122,12 +127,11 @@ pub fn find_graph_roots = select_node.as_ref(&db).dependencies.to_vec(); + v.sort_by(|a, b| a.as_ref(&db).item.cmp(&b.as_ref(&db).item)); + v + }, }]; // process the top item until stack is empty @@ -136,6 +140,14 @@ pub fn find_graph_roots>(); + + edges.sort_by(|a, b| a.item.cmp(&b.item)); + // Process one dependency let dependency = stack[top_of_stack_idx] .open_edges @@ -147,12 +159,11 @@ pub fn find_graph_roots = dependency.as_ref(&db).dependencies.to_vec(); + v.sort_unstable(); + v + }, }); dependency.as_mut(&mut db).marker = Marker::InProgressMarker; } @@ -171,7 +182,7 @@ pub fn find_graph_roots max { + cycle_roots.clear(); + max = dep.as_ref(&db).incoming; + } + cycle_roots.insert(dep); } - if dep.as_ref(&db).incoming < max { - continue; - } - if dep.as_ref(&db).incoming > max { - cycle_roots.clear(); - max = dep.as_ref(&db).incoming; - } - cycle_roots.insert(dep); } } for cycle_root in cycle_roots { diff --git a/crates/rspack_ids/src/id_helpers.rs b/crates/rspack_ids/src/id_helpers.rs index 2cf437ccffa..29bb252b58e 100644 --- a/crates/rspack_ids/src/id_helpers.rs +++ b/crates/rspack_ids/src/id_helpers.rs @@ -229,9 +229,10 @@ pub fn assign_names_par( items.sort_unstable_by(&comparator); let mut i = 0; for item in items { - let formatted_name = format!("{name}{i}"); + let mut formatted_name = format!("{name}{i}"); while name_to_items_keys.contains(&formatted_name) && used_ids.contains(&formatted_name) { i += 1; + formatted_name = format!("{name}{i}"); } assign_name(item, formatted_name.clone()); used_ids.insert(formatted_name); @@ -494,7 +495,7 @@ fn compare_chunks_by_modules( let a_modules = chunk_graph.get_ordered_chunk_modules(&a.ukey, module_graph); let b_modules = chunk_graph.get_ordered_chunk_modules(&b.ukey, module_graph); - a_modules + let eq = a_modules .into_iter() .zip_longest(b_modules) .find_map(|pair| match pair { @@ -513,7 +514,15 @@ fn compare_chunks_by_modules( Left(_) => Some(Ordering::Greater), Right(_) => Some(Ordering::Less), }) - .unwrap_or(Ordering::Equal) + .unwrap_or(Ordering::Equal); + + // 2 chunks are exactly the same, we have to compare + // the ukey to get stable results + if matches!(eq, Ordering::Equal) { + return a.ukey.cmp(&b.ukey); + } + + eq } pub fn compare_chunks_natural(