Skip to content

Commit e8b2dc3

Browse files
authored
perf: improve data structures of bundle splitting (#11506)
1 parent 7e087f2 commit e8b2dc3

File tree

13 files changed

+273
-256
lines changed

13 files changed

+273
-256
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/rspack_collections/src/identifier.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ impl Identifier {
8383
pub fn to_string(&self) -> String {
8484
self.0.to_owned()
8585
}
86+
87+
pub fn precomputed_hash(&self) -> u64 {
88+
self.0.precomputed_hash()
89+
}
8690
}
8791

8892
impl fmt::Display for Identifier {

crates/rspack_core/src/exports/export_info_setter.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::collections::hash_map::Entry;
33
use rspack_util::atom::Atom;
44

55
use super::{ExportInfoData, ExportInfoTargetValue, Inlinable, UsageFilterFnTy, UsageState};
6-
use crate::{DependencyId, ExportsInfo, Nullable, RuntimeSpec};
6+
use crate::{DependencyId, Nullable, RuntimeSpec};
77

88
impl ExportInfoData {
99
pub fn reset_provide_info(&mut self) {
@@ -212,17 +212,12 @@ impl ExportInfoData {
212212
changed
213213
}
214214

215-
pub fn set_has_use_info(&mut self, nested_exports_info: &mut Vec<ExportsInfo>) {
215+
pub fn set_has_use_info(&mut self) {
216216
if !self.has_use_in_runtime_info() {
217217
self.set_has_use_in_runtime_info(true);
218218
}
219219
if self.can_mangle_use().is_none() {
220220
self.set_can_mangle_use(Some(true));
221221
}
222-
if self.exports_info_owned()
223-
&& let Some(exports_info) = self.exports_info()
224-
{
225-
nested_exports_info.push(exports_info);
226-
}
227222
}
228223
}

crates/rspack_core/src/exports/exports_info.rs

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -163,30 +163,6 @@ impl ExportsInfo {
163163
new_info_id
164164
}
165165

166-
pub fn set_has_use_info(&self, mg: &mut ModuleGraph) {
167-
let mut nested_exports_info = vec![];
168-
let exports_info = self.as_data_mut(mg);
169-
for export_info in exports_info.exports_mut().values_mut() {
170-
export_info.set_has_use_info(&mut nested_exports_info);
171-
}
172-
exports_info
173-
.side_effects_only_info_mut()
174-
.set_has_use_info(&mut nested_exports_info);
175-
if let Some(redirect) = exports_info.redirect_to() {
176-
redirect.set_has_use_info(mg);
177-
} else {
178-
let other_exports_info = exports_info.other_exports_info_mut();
179-
other_exports_info.set_has_use_info(&mut nested_exports_info);
180-
if other_exports_info.can_mangle_use().is_none() {
181-
other_exports_info.set_can_mangle_use(Some(true));
182-
}
183-
}
184-
185-
for nested_exports_info in nested_exports_info {
186-
nested_exports_info.set_has_use_info(mg);
187-
}
188-
}
189-
190166
pub fn set_used_without_info(&self, mg: &mut ModuleGraph, runtime: Option<&RuntimeSpec>) -> bool {
191167
let mut changed = false;
192168
let exports_info = self.as_data_mut(mg);

crates/rspack_core/src/exports/utils.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ pub enum ExportProvided {
168168
Unknown,
169169
}
170170

171-
#[derive(Debug, Hash, PartialEq, Eq, Default)]
171+
#[derive(Debug, Hash, PartialEq, Eq, Default, Clone)]
172172
pub struct UsageKey(pub Vec<Either<Box<UsageKey>, UsageState>>);
173173

174174
impl UsageKey {
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
use std::collections::hash_map::Entry;
2+
3+
use rayon::prelude::*;
4+
5+
use crate::{
6+
ExportsInfo, ExportsInfoData, ExportsInfoGetter, ModuleGraph, ModuleIdentifier,
7+
PrefetchExportsInfoMode, PrefetchedExportsInfoWrapper,
8+
};
9+
10+
impl<'a> ModuleGraph<'a> {
11+
pub fn get_exports_info(&self, module_identifier: &ModuleIdentifier) -> ExportsInfo {
12+
self
13+
.module_graph_module_by_identifier(module_identifier)
14+
.expect("should have mgm")
15+
.exports
16+
}
17+
18+
pub fn get_prefetched_exports_info_optional<'b>(
19+
&'b self,
20+
module_identifier: &ModuleIdentifier,
21+
mode: PrefetchExportsInfoMode<'b>,
22+
) -> Option<PrefetchedExportsInfoWrapper<'b>> {
23+
self
24+
.module_graph_module_by_identifier(module_identifier)
25+
.map(move |mgm| ExportsInfoGetter::prefetch(&mgm.exports, self, mode))
26+
}
27+
28+
pub fn get_prefetched_exports_info<'b>(
29+
&'b self,
30+
module_identifier: &ModuleIdentifier,
31+
mode: PrefetchExportsInfoMode<'b>,
32+
) -> PrefetchedExportsInfoWrapper<'b> {
33+
let exports_info = self.get_exports_info(module_identifier);
34+
ExportsInfoGetter::prefetch(&exports_info, self, mode)
35+
}
36+
37+
pub fn get_exports_info_by_id(&self, id: &ExportsInfo) -> &ExportsInfoData {
38+
self
39+
.try_get_exports_info_by_id(id)
40+
.expect("should have exports info")
41+
}
42+
43+
pub fn try_get_exports_info_by_id(&self, id: &ExportsInfo) -> Option<&ExportsInfoData> {
44+
self.loop_partials(|p| p.exports_info_map.get(id))
45+
}
46+
47+
pub fn get_exports_info_mut_by_id(&mut self, id: &ExportsInfo) -> &mut ExportsInfoData {
48+
self
49+
.loop_partials_mut(
50+
|p| p.exports_info_map.contains_key(id),
51+
|p, search_result| {
52+
p.exports_info_map.insert(*id, search_result);
53+
},
54+
|p| p.exports_info_map.get(id).cloned(),
55+
|p| p.exports_info_map.get_mut(id),
56+
)
57+
.expect("should have exports info")
58+
}
59+
60+
pub fn set_exports_info(&mut self, id: ExportsInfo, info: ExportsInfoData) {
61+
let Some(active_partial) = &mut self.active else {
62+
panic!("should have active partial");
63+
};
64+
active_partial.exports_info_map.insert(id, info);
65+
}
66+
67+
pub fn active_all_exports_info(&mut self) {
68+
let active_partial = self.active.as_mut().expect("should have active partial");
69+
for partial in self.partials.iter().rev().flatten() {
70+
for (id, exports_info) in partial.exports_info_map.iter() {
71+
match active_partial.exports_info_map.entry(*id) {
72+
Entry::Occupied(_) => {}
73+
Entry::Vacant(entry) => {
74+
entry.insert(exports_info.clone());
75+
}
76+
}
77+
}
78+
}
79+
}
80+
81+
pub fn reset_all_exports_info_used(&mut self) {
82+
let exports_info_map = &mut self
83+
.active
84+
.as_mut()
85+
.expect("should have active partial")
86+
.exports_info_map;
87+
88+
exports_info_map
89+
.par_iter_mut()
90+
.for_each(|(_, exports_info)| {
91+
for export_info in exports_info.exports_mut().values_mut() {
92+
export_info.set_has_use_info();
93+
}
94+
exports_info.side_effects_only_info_mut().set_has_use_info();
95+
exports_info.other_exports_info_mut().set_has_use_info();
96+
});
97+
}
98+
}

crates/rspack_core/src/module_graph/mod.rs

Lines changed: 2 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ use swc_core::ecma::atoms::Atom;
99

1010
use crate::{
1111
AsyncDependenciesBlock, AsyncDependenciesBlockIdentifier, Compilation, DependenciesBlock,
12-
Dependency, ExportInfo, ExportName, ExportProvided, ExportsInfoGetter, ModuleGraphCacheArtifact,
13-
PrefetchExportsInfoMode, PrefetchedExportsInfoWrapper, RuntimeSpec,
12+
Dependency, ExportInfo, ExportName, ModuleGraphCacheArtifact, RuntimeSpec,
1413
};
1514
mod module;
1615
pub use module::*;
1716
mod connection;
1817
pub use connection::*;
18+
mod exports_info;
1919

2020
use crate::{
2121
BoxDependency, BoxModule, DependencyCondition, DependencyId, ExportsInfo, ExportsInfoData,
@@ -1026,62 +1026,6 @@ impl<'a> ModuleGraph<'a> {
10261026
new_mgm.add_incoming_connection(*dep_id);
10271027
}
10281028

1029-
pub fn get_exports_info(&self, module_identifier: &ModuleIdentifier) -> ExportsInfo {
1030-
self
1031-
.module_graph_module_by_identifier(module_identifier)
1032-
.expect("should have mgm")
1033-
.exports
1034-
}
1035-
1036-
pub fn get_prefetched_exports_info_optional<'b>(
1037-
&'b self,
1038-
module_identifier: &ModuleIdentifier,
1039-
mode: PrefetchExportsInfoMode<'b>,
1040-
) -> Option<PrefetchedExportsInfoWrapper<'b>> {
1041-
self
1042-
.module_graph_module_by_identifier(module_identifier)
1043-
.map(move |mgm| ExportsInfoGetter::prefetch(&mgm.exports, self, mode))
1044-
}
1045-
1046-
pub fn get_prefetched_exports_info<'b>(
1047-
&'b self,
1048-
module_identifier: &ModuleIdentifier,
1049-
mode: PrefetchExportsInfoMode<'b>,
1050-
) -> PrefetchedExportsInfoWrapper<'b> {
1051-
let exports_info = self.get_exports_info(module_identifier);
1052-
ExportsInfoGetter::prefetch(&exports_info, self, mode)
1053-
}
1054-
1055-
pub fn get_exports_info_by_id(&self, id: &ExportsInfo) -> &ExportsInfoData {
1056-
self
1057-
.try_get_exports_info_by_id(id)
1058-
.expect("should have exports info")
1059-
}
1060-
1061-
pub fn try_get_exports_info_by_id(&self, id: &ExportsInfo) -> Option<&ExportsInfoData> {
1062-
self.loop_partials(|p| p.exports_info_map.get(id))
1063-
}
1064-
1065-
pub fn get_exports_info_mut_by_id(&mut self, id: &ExportsInfo) -> &mut ExportsInfoData {
1066-
self
1067-
.loop_partials_mut(
1068-
|p| p.exports_info_map.contains_key(id),
1069-
|p, search_result| {
1070-
p.exports_info_map.insert(*id, search_result);
1071-
},
1072-
|p| p.exports_info_map.get(id).cloned(),
1073-
|p| p.exports_info_map.get_mut(id),
1074-
)
1075-
.expect("should have exports info")
1076-
}
1077-
1078-
pub fn set_exports_info(&mut self, id: ExportsInfo, info: ExportsInfoData) {
1079-
let Some(active_partial) = &mut self.active else {
1080-
panic!("should have active partial");
1081-
};
1082-
active_partial.exports_info_map.insert(id, info);
1083-
}
1084-
10851029
pub fn get_optimization_bailout_mut(&mut self, id: &ModuleIdentifier) -> &mut Vec<String> {
10861030
let mgm = self
10871031
.module_graph_module_by_identifier_mut(id)
@@ -1108,22 +1052,6 @@ impl<'a> ModuleGraph<'a> {
11081052
condition.get_connection_state(connection, runtime, self, module_graph_cache)
11091053
}
11101054

1111-
// returns: Option<bool>
1112-
// - None: it's unknown
1113-
// - Some(true): provided
1114-
// - Some(false): not provided
1115-
pub fn is_export_provided(
1116-
&self,
1117-
id: &ModuleIdentifier,
1118-
names: &[Atom],
1119-
) -> Option<ExportProvided> {
1120-
self.module_graph_module_by_identifier(id).and_then(|mgm| {
1121-
let exports_info =
1122-
ExportsInfoGetter::prefetch(&mgm.exports, self, PrefetchExportsInfoMode::Nested(names));
1123-
exports_info.is_export_provided(names)
1124-
})
1125-
}
1126-
11271055
// todo remove it after module_graph_partial remove all of dependency_id_to_*
11281056
pub fn cache_recovery_connection(&mut self, connection: ModuleGraphConnection) {
11291057
let condition = self

crates/rspack_plugin_javascript/src/plugin/flag_dependency_usage_plugin.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,16 @@ impl<'a> FlagDependencyUsagePluginProxy<'a> {
4848

4949
fn apply(&mut self) {
5050
let mut module_graph = self.compilation.get_module_graph_mut();
51+
module_graph.active_all_exports_info();
52+
module_graph.reset_all_exports_info_used();
53+
5154
for mgm in module_graph.module_graph_modules().values() {
5255
self
5356
.exports_info_module_map
5457
.insert(mgm.exports, mgm.module_identifier);
5558
}
5659
let mut q = Queue::new();
5760
let mg = &mut module_graph;
58-
for exports_info in self.exports_info_module_map.keys() {
59-
exports_info.set_has_use_info(mg);
60-
}
6161

6262
// SAFETY: we can make sure that entries will not be used other place at the same time,
6363
// this take is aiming to avoid use self ref and mut ref at the same time;

crates/rspack_plugin_split_chunks/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ version.workspace = true
1212
dashmap = { workspace = true }
1313
derive_more = { workspace = true, features = ["debug"] }
1414
futures = { workspace = true }
15+
itertools = { workspace = true }
1516
rayon = { workspace = true }
1617
regex = { workspace = true }
1718
rspack_collections = { workspace = true }

0 commit comments

Comments
 (0)