Skip to content

Commit 521bd77

Browse files
mischnicsokra
authored andcommitted
use hashset for ChunkGroup entries
1 parent 76d8875 commit 521bd77

File tree

5 files changed

+110
-51
lines changed

5 files changed

+110
-51
lines changed

crates/next-api/src/app.rs

+17-11
Original file line numberDiff line numberDiff line change
@@ -1671,7 +1671,7 @@ impl AppEndpoint {
16711671
let entry_chunk_group_idx = *module_graph
16721672
.chunk_group_info()
16731673
.get_index_of(ChunkGroup::Entry {
1674-
entries: vec![ResolvedVc::upcast(rsc_entry)],
1674+
entries: [ResolvedVc::upcast(rsc_entry)].into_iter().collect(),
16751675
ty: ChunkGroupType::Entry,
16761676
})
16771677
.await?;
@@ -1689,7 +1689,9 @@ impl AppEndpoint {
16891689
.iter()
16901690
.map(async |m| Ok(ResolvedVc::upcast(m.await?.module)))
16911691
.try_join()
1692-
.await?;
1692+
.await?
1693+
.into_iter()
1694+
.collect();
16931695
let chunk_group = chunking_context
16941696
.chunk_group(
16951697
AssetIdent::from_path(
@@ -1756,15 +1758,19 @@ impl AppEndpoint {
17561758
}
17571759

17581760
current_chunks = current_chunks
1759-
.concatenate(chunking_context.chunk_group_assets(
1760-
server_action_manifest_loader.ident(),
1761-
ChunkGroup::Entry {
1762-
entries: vec![ResolvedVc::upcast(server_action_manifest_loader)],
1763-
ty: ChunkGroupType::Entry,
1764-
},
1765-
module_graph,
1766-
Value::new(current_availability_info),
1767-
))
1761+
.concatenate(
1762+
chunking_context.chunk_group_assets(
1763+
server_action_manifest_loader.ident(),
1764+
ChunkGroup::Entry {
1765+
entries: [ResolvedVc::upcast(server_action_manifest_loader)]
1766+
.into_iter()
1767+
.collect(),
1768+
ty: ChunkGroupType::Entry,
1769+
},
1770+
module_graph,
1771+
Value::new(current_availability_info),
1772+
),
1773+
)
17681774
.resolve()
17691775
.await?;
17701776

crates/next-core/src/next_app/app_client_references_chunks.rs

+14-29
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ use anyhow::Result;
22
use tracing::Instrument;
33
use turbo_rcstr::RcStr;
44
use turbo_tasks::{
5-
FxIndexMap, FxIndexSet, ResolvedVc, TryFlatJoinIterExt, TryJoinIterExt, Value, ValueToString,
6-
Vc,
5+
primitives::HashableHashSet, FxIndexMap, ResolvedVc, TryFlatJoinIterExt, TryJoinIterExt, Value,
6+
ValueToString, Vc,
77
};
88
use turbo_tasks_fs::FileSystemPath;
99
use turbopack_core::{
@@ -198,7 +198,7 @@ pub async fn get_app_client_references_chunks(
198198
ChunkGroup::SharedMerged {
199199
parent: *chunk_group_info
200200
.get_index_of(ChunkGroup::Entry {
201-
entries: vec![rsc_entry],
201+
entries: [rsc_entry].into_iter().collect(),
202202
ty: ChunkGroupType::Entry,
203203
})
204204
.await?,
@@ -208,7 +208,9 @@ pub async fn get_app_client_references_chunks(
208208
.iter()
209209
.map(async |m| Ok(ResolvedVc::upcast(m.await?.module)))
210210
.try_join()
211-
.await?,
211+
.await?
212+
.into_iter()
213+
.collect(),
212214
}
213215
})
214216
.await?;
@@ -229,7 +231,7 @@ pub async fn get_app_client_references_chunks(
229231
)
230232
};
231233

232-
let mut ssr_modules = client_reference_types
234+
let ssr_modules: HashableHashSet<_> = client_reference_types
233235
.iter()
234236
.map(|client_reference_ty| async move {
235237
Ok(match client_reference_ty {
@@ -247,18 +249,9 @@ pub async fn get_app_client_references_chunks(
247249
})
248250
})
249251
.try_flat_join()
250-
.await?;
251-
if server_component.is_none() {
252-
// client_reference_types contains every client reference proxy twice
253-
// (<evaluation> and the regular module), so mapping this into ssr_module leads
254-
// to duplicates.
255-
ssr_modules = ssr_modules
256-
.into_iter()
257-
.collect::<FxIndexSet<_>>()
258-
.into_iter()
259-
.collect();
260-
}
261-
252+
.await?
253+
.into_iter()
254+
.collect();
262255
let ssr_chunk_group = if !ssr_modules.is_empty() {
263256
ssr_chunking_context.map(|ssr_chunking_context| {
264257
let _span = tracing::info_span!(
@@ -282,7 +275,7 @@ pub async fn get_app_client_references_chunks(
282275
None
283276
};
284277

285-
let mut client_modules = client_reference_types
278+
let client_modules: HashableHashSet<_> = client_reference_types
286279
.iter()
287280
.map(|client_reference_ty| async move {
288281
Ok(match client_reference_ty {
@@ -297,17 +290,9 @@ pub async fn get_app_client_references_chunks(
297290
})
298291
})
299292
.try_join()
300-
.await?;
301-
if server_component.is_none() {
302-
// client_reference_types contains every client reference proxy twice
303-
// (<evaluation> and the regular module), so mapping this into client_modules
304-
// leads to duplicates.
305-
client_modules = client_modules
306-
.into_iter()
307-
.collect::<FxIndexSet<_>>()
308-
.into_iter()
309-
.collect();
310-
}
293+
.await?
294+
.into_iter()
295+
.collect();
311296
let client_chunk_group = if !client_modules.is_empty() {
312297
let _span = tracing::info_span!(
313298
"client side rendering",

turbopack/crates/turbo-tasks/src/primitives.rs

+69-4
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
1-
use std::{ops::Deref, time::Duration};
1+
use std::{
2+
hash::{Hash, Hasher},
3+
ops::Deref,
4+
time::Duration,
5+
};
26

7+
use anyhow::Result;
8+
use rustc_hash::{FxHashSet, FxHasher};
9+
use serde::{Deserialize, Serialize};
310
use turbo_rcstr::RcStr;
411
// This specific macro identifier is detected by turbo-tasks-build.
512
use turbo_tasks_macros::primitive as __turbo_tasks_internal_primitive;
613

7-
use crate::{
8-
Vc, {self as turbo_tasks},
9-
};
14+
use crate::{self as turbo_tasks, TaskInput, Vc};
1015

1116
__turbo_tasks_internal_primitive!(());
1217
__turbo_tasks_internal_primitive!(String, manual_shrink_to_fit);
@@ -57,3 +62,63 @@ impl PartialEq for Regex {
5762
}
5863
}
5964
impl Eq for Regex {}
65+
66+
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
67+
#[serde(bound(
68+
deserialize = "T: Hash + Eq + Deserialize<'de>",
69+
serialize = "T: Hash + Eq + Serialize"
70+
))]
71+
pub struct HashableHashSet<T: Hash + Eq>(pub FxHashSet<T>);
72+
73+
impl<T: Hash + Eq> From<FxHashSet<T>> for HashableHashSet<T> {
74+
fn from(set: FxHashSet<T>) -> Self {
75+
HashableHashSet(set)
76+
}
77+
}
78+
79+
impl<T: Hash + Eq> FromIterator<T> for HashableHashSet<T> {
80+
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
81+
HashableHashSet(iter.into_iter().collect())
82+
}
83+
}
84+
85+
impl<T: Hash + Eq> Deref for HashableHashSet<T> {
86+
type Target = FxHashSet<T>;
87+
88+
fn deref(&self) -> &Self::Target {
89+
&self.0
90+
}
91+
}
92+
impl<T: Hash + Eq> Hash for HashableHashSet<T> {
93+
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
94+
let mut result = 0u64;
95+
for item in self.iter() {
96+
let mut hasher = FxHasher::default();
97+
item.hash(&mut hasher);
98+
let item_hash = hasher.finish();
99+
result ^= item_hash;
100+
}
101+
state.write_u64(result);
102+
}
103+
}
104+
105+
impl<T> TaskInput for HashableHashSet<T>
106+
where
107+
T: TaskInput,
108+
{
109+
fn is_resolved(&self) -> bool {
110+
self.iter().all(TaskInput::is_resolved)
111+
}
112+
113+
fn is_transient(&self) -> bool {
114+
self.iter().any(TaskInput::is_transient)
115+
}
116+
117+
async fn resolve_input(&self) -> Result<Self> {
118+
let mut resolved = FxHashSet::with_capacity_and_hasher(self.len(), Default::default());
119+
for value in self.iter() {
120+
resolved.insert(value.resolve_input().await?);
121+
}
122+
Ok(resolved.into())
123+
}
124+
}

turbopack/crates/turbopack-core/src/module_graph/chunk_group_info.rs

+9-6
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ use serde::{Deserialize, Serialize};
1414
use tracing::Instrument;
1515
use turbo_rcstr::RcStr;
1616
use turbo_tasks::{
17-
debug::ValueDebugFormat, trace::TraceRawVcs, FxIndexMap, FxIndexSet, NonLocalValue, ResolvedVc,
18-
TaskInput, TryJoinIterExt, ValueToString, Vc,
17+
debug::ValueDebugFormat, primitives::HashableHashSet, trace::TraceRawVcs, FxIndexMap,
18+
FxIndexSet, NonLocalValue, ResolvedVc, TaskInput, TryJoinIterExt, ValueToString, Vc,
1919
};
2020

2121
use crate::{
@@ -128,7 +128,7 @@ impl ChunkGroupInfo {
128128
pub enum ChunkGroup {
129129
/// e.g. a page
130130
Entry {
131-
entries: Vec<ResolvedVc<Box<dyn Module>>>,
131+
entries: HashableHashSet<ResolvedVc<Box<dyn Module>>>,
132132
ty: ChunkGroupType,
133133
},
134134
/// a module with an incoming async edge
@@ -139,15 +139,15 @@ pub enum ChunkGroup {
139139
IsolatedMerged {
140140
parent: usize,
141141
merge_tag: RcStr,
142-
entries: Vec<ResolvedVc<Box<dyn Module>>>,
142+
entries: HashableHashSet<ResolvedVc<Box<dyn Module>>>,
143143
},
144144
/// a module with an incoming non-merging shared edge
145145
Shared(ResolvedVc<Box<dyn Module>>),
146146
/// a module with an incoming merging shared edge
147147
SharedMerged {
148148
parent: usize,
149149
merge_tag: RcStr,
150-
entries: Vec<ResolvedVc<Box<dyn Module>>>,
150+
entries: HashableHashSet<ResolvedVc<Box<dyn Module>>>,
151151
},
152152
}
153153

@@ -621,7 +621,10 @@ pub async fn compute_chunk_group_info(graph: &ModuleGraph) -> Result<Vc<ChunkGro
621621
chunk_groups: chunk_groups_map
622622
.into_iter()
623623
.map(|(k, (_, merged_entries))| match k {
624-
ChunkGroupKey::Entry { entries, ty } => ChunkGroup::Entry { entries, ty },
624+
ChunkGroupKey::Entry { entries, ty } => ChunkGroup::Entry {
625+
entries: entries.into_iter().collect(),
626+
ty,
627+
},
625628
ChunkGroupKey::Async(module) => ChunkGroup::Async(module),
626629
ChunkGroupKey::Isolated(module) => ChunkGroup::Isolated(module),
627630
ChunkGroupKey::IsolatedMerged { parent, merge_tag } => {

turbopack/crates/turbopack-dev-server/src/html.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ impl DevHtmlAsset {
164164
chunking_context.root_chunk_group_assets(
165165
chunkable_module.ident(),
166166
ChunkGroup::Entry {
167-
entries: vec![ResolvedVc::upcast(chunkable_module)],
167+
entries: [ResolvedVc::upcast(chunkable_module)].into_iter().collect(),
168168
ty: ChunkGroupType::Evaluated,
169169
},
170170
*module_graph,

0 commit comments

Comments
 (0)