-
Notifications
You must be signed in to change notification settings - Fork 27.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Turbopack] fix a bunch of bugs and inefficiencies in the call graph #70243
Changes from all commits
d911897
1fe68bc
cf5089e
62ff997
d4cdf51
dc8eae0
e61889c
46b5ade
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -268,8 +268,11 @@ struct MaybeCollectibles { | |
|
||
impl MaybeCollectibles { | ||
/// Consumes the collectibles (if any) and return them. | ||
fn take_collectibles(&mut self) -> Option<Collectibles> { | ||
self.inner.as_mut().map(|boxed| take(&mut **boxed)) | ||
fn take_collectibles(&mut self) -> Collectibles { | ||
self.inner | ||
.as_mut() | ||
.map(|boxed| take(&mut **boxed)) | ||
.unwrap_or_default() | ||
Comment on lines
+271
to
+275
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need for additional Option wrapping |
||
} | ||
|
||
/// Consumes the collectibles (if any) and return them. | ||
|
@@ -305,6 +308,23 @@ impl MaybeCollectibles { | |
.or_default(); | ||
*value -= count as i32; | ||
} | ||
|
||
/// Removes an collectible if the count is positive. | ||
fn remove_emit(&mut self, trait_type: TraitTypeId, value: RawVc) -> bool { | ||
let Some(inner) = self.inner.as_mut() else { | ||
return false; | ||
}; | ||
|
||
let auto_hash_map::map::Entry::Occupied(mut e) = inner.entry((trait_type, value)) else { | ||
return false; | ||
}; | ||
let value = e.get_mut(); | ||
*value -= 1; | ||
if *value == 0 { | ||
e.remove(); | ||
} | ||
true | ||
} | ||
} | ||
|
||
struct InProgressState { | ||
|
@@ -828,32 +848,32 @@ impl Task { | |
let outdated_children = outdated_edges.drain_children(); | ||
let outdated_collectibles = outdated_collectibles.take_collectibles(); | ||
|
||
let remove_job = if outdated_children.is_empty() { | ||
None | ||
} else { | ||
state.aggregation_node.handle_lost_edges( | ||
&aggregation_context, | ||
&self.id, | ||
outdated_children, | ||
) | ||
}; | ||
|
||
let mut change = TaskChange { | ||
unfinished: -1, | ||
#[cfg(feature = "track_unfinished")] | ||
unfinished_tasks_update: vec![(self.id, -1)], | ||
..Default::default() | ||
}; | ||
if let Some(collectibles) = outdated_collectibles { | ||
for ((trait_type, value), count) in collectibles.into_iter() { | ||
change.collectibles.push((trait_type, value, -count)); | ||
} | ||
for ((trait_type, value), count) in outdated_collectibles.into_iter() { | ||
change.collectibles.push((trait_type, value, -count)); | ||
} | ||
let change_job = state | ||
.aggregation_node | ||
.apply_change(&aggregation_context, change); | ||
let remove_job = if outdated_children.is_empty() { | ||
None | ||
} else { | ||
Some(state.aggregation_node.handle_lost_edges( | ||
&aggregation_context, | ||
&self.id, | ||
outdated_children, | ||
)) | ||
}; | ||
|
||
drop(state); | ||
change_job.apply(&aggregation_context); | ||
remove_job.apply(&aggregation_context); | ||
change_job.apply(&aggregation_context); | ||
Comment on lines
875
to
+876
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Less work if we remove first |
||
} | ||
aggregation_context.apply_queued_updates(); | ||
} | ||
|
@@ -984,9 +1004,9 @@ impl Task { | |
for child in new_children { | ||
outdated_edges.insert(TaskEdge::Child(child)); | ||
} | ||
if let Some(collectibles) = outdated_collectibles { | ||
if !outdated_collectibles.is_empty() { | ||
let mut change = TaskChange::default(); | ||
for ((trait_type, value), count) in collectibles.into_iter() { | ||
for ((trait_type, value), count) in outdated_collectibles.into_iter() { | ||
change.collectibles.push((trait_type, value, -count)); | ||
} | ||
change_job = state | ||
|
@@ -1008,7 +1028,6 @@ impl Task { | |
outdated_edges.remove_all(&new_edges); | ||
for child in new_children { | ||
new_edges.insert(TaskEdge::Child(child)); | ||
outdated_edges.remove(TaskEdge::Child(child)); | ||
} | ||
if !backend.has_gc() { | ||
// This will stay here for longer, so make sure to not consume too | ||
|
@@ -1022,38 +1041,37 @@ impl Task { | |
stateful, | ||
edges: new_edges.into_list(), | ||
}; | ||
let outdated_children = outdated_edges.drain_children(); | ||
if !outdated_children.is_empty() { | ||
remove_job = state.aggregation_node.handle_lost_edges( | ||
&aggregation_context, | ||
&self.id, | ||
outdated_children, | ||
); | ||
} | ||
if !count_as_finished { | ||
let mut change = TaskChange { | ||
unfinished: -1, | ||
#[cfg(feature = "track_unfinished")] | ||
unfinished_tasks_update: vec![(self.id, -1)], | ||
..Default::default() | ||
}; | ||
if let Some(collectibles) = outdated_collectibles { | ||
for ((trait_type, value), count) in collectibles.into_iter() { | ||
change.collectibles.push((trait_type, value, -count)); | ||
} | ||
for ((trait_type, value), count) in outdated_collectibles.into_iter() { | ||
change.collectibles.push((trait_type, value, -count)); | ||
} | ||
change_job = state | ||
.aggregation_node | ||
.apply_change(&aggregation_context, change); | ||
} else if let Some(collectibles) = outdated_collectibles { | ||
} else if !outdated_collectibles.is_empty() { | ||
let mut change = TaskChange::default(); | ||
for ((trait_type, value), count) in collectibles.into_iter() { | ||
for ((trait_type, value), count) in outdated_collectibles.into_iter() { | ||
change.collectibles.push((trait_type, value, -count)); | ||
} | ||
change_job = state | ||
.aggregation_node | ||
.apply_change(&aggregation_context, change); | ||
} | ||
let outdated_children = outdated_edges.drain_children(); | ||
if !outdated_children.is_empty() { | ||
remove_job = state.aggregation_node.handle_lost_edges( | ||
&aggregation_context, | ||
&self.id, | ||
outdated_children, | ||
); | ||
} | ||
|
||
done_event.notify(usize::MAX); | ||
drop(state); | ||
self.clear_dependencies(outdated_edges, backend, turbo_tasks); | ||
|
@@ -1062,8 +1080,8 @@ impl Task { | |
for cell in drained_cells { | ||
cell.gc_drop(turbo_tasks); | ||
} | ||
change_job.apply(&aggregation_context); | ||
remove_job.apply(&aggregation_context); | ||
change_job.apply(&aggregation_context); | ||
} | ||
if let TaskType::Once(_) = self.ty { | ||
// unset the root type, so tasks below are no longer active | ||
|
@@ -1680,9 +1698,18 @@ impl Task { | |
backend: &MemoryBackend, | ||
turbo_tasks: &dyn TurboTasksBackendApi<MemoryBackend>, | ||
) { | ||
let mut aggregation_context = TaskAggregationContext::new(turbo_tasks, backend); | ||
let mut state = self.full_state_mut(); | ||
state.collectibles.emit(trait_type, collectible); | ||
if let TaskStateType::InProgress(box InProgressState { | ||
outdated_collectibles, | ||
.. | ||
}) = &mut state.state_type | ||
{ | ||
if outdated_collectibles.remove_emit(trait_type, collectible) { | ||
return; | ||
} | ||
} | ||
Comment on lines
+1703
to
+1711
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On recomputation it's possible that the same collectible is emitted again. This adds an optimization, that if a collectible is an "outdated" collectible (a collectible that was emitted in the previous computation), we reuse that by removing it from "outdated" so we don't need to propagate it through the graph. So 0 propagations instead of 2 (add, remove). |
||
let mut aggregation_context = TaskAggregationContext::new(turbo_tasks, backend); | ||
let change_job = state.aggregation_node.apply_change( | ||
&aggregation_context, | ||
TaskChange { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some obvious bugs...