Skip to content

Commit f6c2d49

Browse files
authored
Turbopack: add task_id_details feature (#84970)
### What? Add a bunch of feature flags that help debugging cases where it is loosing invalidations.
1 parent 9375bc3 commit f6c2d49

File tree

8 files changed

+110
-14
lines changed

8 files changed

+110
-14
lines changed

turbopack/crates/turbo-tasks-backend/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ trace_aggregation_update = []
2424
trace_find_and_schedule = []
2525
trace_task_completion = []
2626
trace_task_dirty = []
27+
trace_task_output_dependencies = []
28+
trace_task_details = []
2729
lmdb = ["dep:lmdb-rkv"]
2830

2931
[dependencies]

turbopack/crates/turbo-tasks-backend/src/backend/mod.rs

Lines changed: 58 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use parking_lot::{Condvar, Mutex};
2424
use rustc_hash::{FxHashMap, FxHashSet, FxHasher};
2525
use smallvec::{SmallVec, smallvec};
2626
use tokio::time::{Duration, Instant};
27-
use tracing::{Span, field::Empty, info_span, trace_span};
27+
use tracing::{Span, info_span, trace_span};
2828
use turbo_tasks::{
2929
CellId, FxDashMap, FxIndexMap, KeyValuePair, RawVc, ReadCellOptions, ReadConsistency,
3030
ReadOutputOptions, ReadTracking, SessionId, TRANSIENT_TASK_BIT, TaskExecutionReason, TaskId,
@@ -722,21 +722,23 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
722722
let result = match output {
723723
OutputValue::Cell(cell) => Ok(Ok(RawVc::TaskCell(cell.task, cell.cell))),
724724
OutputValue::Output(task) => Ok(Ok(RawVc::TaskOutput(*task))),
725-
OutputValue::Error(error) => {
726-
let err: anyhow::Error = error.clone().into();
727-
Err(err.context(format!(
728-
"Execution of {} failed",
729-
ctx.get_task_description(task_id)
730-
)))
731-
}
725+
OutputValue::Error(error) => Err(error
726+
.with_task_context(ctx.get_task_description(task_id), Some(task_id))
727+
.into()),
732728
};
733729
if let Some(mut reader_task) = reader_task
734730
&& options.tracking.should_track(result.is_err())
735731
&& (!task.is_immutable() || cfg!(feature = "verify_immutable"))
736732
{
737-
let reader = reader.unwrap();
733+
#[cfg(feature = "trace_task_output_dependencies")]
734+
let _span = tracing::trace_span!(
735+
"add output dependency",
736+
task = %task_id,
737+
dependent_task = ?reader
738+
)
739+
.entered();
738740
let _ = task.add(CachedDataItem::OutputDependent {
739-
task: reader,
741+
task: reader.unwrap(),
740742
value: (),
741743
});
742744
drop(task);
@@ -1763,7 +1765,22 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
17631765
// The task might be invalidated during this process, so we need to check the stale flag
17641766
// at the start of every step.
17651767

1766-
let span = tracing::trace_span!("task execution completed", immutable = Empty).entered();
1768+
#[cfg(not(feature = "trace_task_details"))]
1769+
let _span = tracing::trace_span!("task execution completed").entered();
1770+
#[cfg(feature = "trace_task_details")]
1771+
let span = tracing::trace_span!(
1772+
"task execution completed",
1773+
task_id = display(task_id),
1774+
result = match result.as_ref() {
1775+
Ok(value) => display(either::Either::Left(value)),
1776+
Err(err) => display(either::Either::Right(err)),
1777+
},
1778+
immutable = tracing::field::Empty,
1779+
new_output = tracing::field::Empty,
1780+
output_dependents = tracing::field::Empty,
1781+
stale = tracing::field::Empty,
1782+
)
1783+
.entered();
17671784
let mut ctx = self.execute_context(turbo_tasks);
17681785

17691786
let Some(TaskExecutionCompletePrepareResult {
@@ -1776,6 +1793,7 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
17761793
output_dependent_tasks,
17771794
}) = self.task_execution_completed_prepare(
17781795
&mut ctx,
1796+
#[cfg(feature = "trace_task_details")]
17791797
&span,
17801798
task_id,
17811799
result,
@@ -1785,9 +1803,16 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
17851803
)
17861804
else {
17871805
// Task was stale and has been rescheduled
1806+
#[cfg(feature = "trace_task_details")]
1807+
span.record("stale", "true");
17881808
return true;
17891809
};
17901810

1811+
#[cfg(feature = "trace_task_details")]
1812+
span.record("new_output", new_output.is_some());
1813+
#[cfg(feature = "trace_task_details")]
1814+
span.record("output_dependents", output_dependent_tasks.len());
1815+
17911816
// When restoring from filesystem cache the following might not be executed (since we can
17921817
// suspend in `CleanupOldEdgesOperation`), but that's ok as the task is still dirty and
17931818
// would be executed again.
@@ -1810,6 +1835,8 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
18101835
&& self.task_execution_completed_connect(&mut ctx, task_id, new_children)
18111836
{
18121837
// Task was stale and has been rescheduled
1838+
#[cfg(feature = "trace_task_details")]
1839+
span.record("stale", "true");
18131840
return true;
18141841
}
18151842

@@ -1823,6 +1850,8 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
18231850
is_now_immutable,
18241851
) {
18251852
// Task was stale and has been rescheduled
1853+
#[cfg(feature = "trace_task_details")]
1854+
span.record("stale", "true");
18261855
return true;
18271856
}
18281857

@@ -1836,7 +1865,7 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
18361865
fn task_execution_completed_prepare(
18371866
&self,
18381867
ctx: &mut impl ExecuteContext<'_>,
1839-
span: &Span,
1868+
#[cfg(feature = "trace_task_details")] span: &Span,
18401869
task_id: TaskId,
18411870
result: Result<RawVc, TurboTasksExecutionError>,
18421871
cell_counters: &AutoMap<ValueTypeId, u32, BuildHasherDefault<FxHasher>, 8>,
@@ -2088,6 +2117,7 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
20882117
{
20892118
is_now_immutable = true;
20902119
}
2120+
#[cfg(feature = "trace_task_details")]
20912121
span.record("immutable", is_immutable || is_now_immutable);
20922122

20932123
if !queue.is_empty() || !old_edges.is_empty() {
@@ -2120,19 +2150,33 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
21202150

21212151
let mut queue = AggregationUpdateQueue::new();
21222152
for dependent_task_id in output_dependent_tasks {
2153+
#[cfg(feature = "trace_task_output_dependencies")]
2154+
let span = tracing::trace_span!(
2155+
"invalidate output dependency",
2156+
task = %task_id,
2157+
dependent_task = %dependent_task_id,
2158+
result = tracing::field::Empty,
2159+
)
2160+
.entered();
21232161
if ctx.is_once_task(dependent_task_id) {
21242162
// once tasks are never invalidated
2163+
#[cfg(feature = "trace_task_output_dependencies")]
2164+
span.record("result", "once task");
21252165
continue;
21262166
}
21272167
let dependent = ctx.task(dependent_task_id, TaskDataCategory::All);
21282168
if dependent.has_key(&CachedDataItemKey::OutdatedOutputDependency { target: task_id }) {
21292169
// output dependency is outdated, so it hasn't read the output yet
21302170
// and doesn't need to be invalidated
2171+
#[cfg(feature = "trace_task_output_dependencies")]
2172+
span.record("result", "outdated dependency");
21312173
continue;
21322174
}
21332175
if !dependent.has_key(&CachedDataItemKey::OutputDependency { target: task_id }) {
21342176
// output dependency has been removed, so the task doesn't depend on the
21352177
// output anymore and doesn't need to be invalidated
2178+
#[cfg(feature = "trace_task_output_dependencies")]
2179+
span.record("result", "no backward dependency");
21362180
continue;
21372181
}
21382182
make_task_dirty_internal(
@@ -2144,6 +2188,8 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
21442188
&mut queue,
21452189
ctx,
21462190
);
2191+
#[cfg(feature = "trace_task_output_dependencies")]
2192+
span.record("result", "marked dirty");
21472193
}
21482194

21492195
queue.execute(ctx);

turbopack/crates/turbo-tasks-backend/src/backend/operation/cleanup_old_edges.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,13 @@ impl Operation for CleanupOldEdgesOperation {
182182
}
183183
}
184184
OutdatedEdge::OutputDependency(output_task_id) => {
185+
#[cfg(feature = "trace_task_output_dependencies")]
186+
let _span = tracing::trace_span!(
187+
"remove output dependency",
188+
task = %output_task_id,
189+
dependent_task = %task_id
190+
)
191+
.entered();
185192
{
186193
let mut task = ctx.task(output_task_id, TaskDataCategory::Data);
187194
task.remove(&CachedDataItemKey::OutputDependent {

turbopack/crates/turbo-tasks-backend/src/backend/operation/invalidate.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ pub fn make_task_dirty_internal(
224224
#[cfg(feature = "trace_task_dirty")]
225225
let _span = tracing::trace_span!(
226226
"make task stale",
227+
task_id = display(task_id),
227228
name = ctx.get_task_description(task_id),
228229
cause = %TaskDirtyCauseInContext::new(&cause, ctx)
229230
)
@@ -244,6 +245,7 @@ pub fn make_task_dirty_internal(
244245
#[cfg(feature = "trace_task_dirty")]
245246
let _span = tracing::trace_span!(
246247
"task already dirty",
248+
task_id = display(task_id),
247249
name = ctx.get_task_description(task_id),
248250
cause = %TaskDirtyCauseInContext::new(&cause, ctx)
249251
)
@@ -275,6 +277,7 @@ pub fn make_task_dirty_internal(
275277
#[cfg(feature = "trace_task_dirty")]
276278
let _span = tracing::trace_span!(
277279
"make task dirty",
280+
task_id = display(task_id),
278281
name = ctx.get_task_description(task_id),
279282
cause = %TaskDirtyCauseInContext::new(&cause, ctx)
280283
)

turbopack/crates/turbo-tasks/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ bench = false
1212
default = []
1313
tokio_tracing = ["tokio/tracing"]
1414
hanging_detection = []
15+
task_id_details = []
1516

1617
# TODO(bgw): This feature is here to unblock turning on local tasks by default. It's only turned on
1718
# in unit tests. This will be removed very soon.

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,8 @@ pub struct TurboTasksError {
427427
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
428428
pub struct TurboTaskContextError {
429429
pub task: RcStr,
430+
#[cfg(feature = "task_id_details")]
431+
pub task_id: Option<TaskId>,
430432
pub source: Option<TurboTasksExecutionError>,
431433
}
432434

@@ -438,9 +440,11 @@ pub enum TurboTasksExecutionError {
438440
}
439441

440442
impl TurboTasksExecutionError {
441-
pub fn with_task_context(&self, task: impl Display) -> Self {
443+
pub fn with_task_context(&self, task: impl Display, _task_id: Option<TaskId>) -> Self {
442444
TurboTasksExecutionError::TaskContext(Arc::new(TurboTaskContextError {
443445
task: RcStr::from(task.to_string()),
446+
#[cfg(feature = "task_id_details")]
447+
task_id: _task_id,
444448
source: Some(self.clone()),
445449
}))
446450
}
@@ -468,6 +472,14 @@ impl Display for TurboTasksExecutionError {
468472
write!(f, "{}", error.message)
469473
}
470474
TurboTasksExecutionError::TaskContext(context_error) => {
475+
#[cfg(feature = "task_id_details")]
476+
if let Some(task_id) = context_error.task_id {
477+
return write!(
478+
f,
479+
"Execution of {} ({}) failed",
480+
context_error.task, task_id
481+
);
482+
}
471483
write!(f, "Execution of {} failed", context_error.task)
472484
}
473485
}

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,15 @@ pub enum TaskPersistence {
281281
Transient,
282282
}
283283

284+
impl Display for TaskPersistence {
285+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
286+
match self {
287+
TaskPersistence::Persistent => write!(f, "persistent"),
288+
TaskPersistence::Transient => write!(f, "transient"),
289+
}
290+
}
291+
}
292+
284293
#[derive(Clone, Copy, Debug, Eq, PartialEq, Default)]
285294
pub enum ReadConsistency {
286295
/// The default behavior for most APIs. Reads are faster, but may return stale values, which
@@ -826,7 +835,7 @@ impl<B: Backend + 'static> TurboTasks<B> {
826835
let output = match result {
827836
Ok(raw_vc) => OutputContent::Link(raw_vc),
828837
Err(err) => OutputContent::Error(
829-
TurboTasksExecutionError::from(err).with_task_context(task_type),
838+
TurboTasksExecutionError::from(err).with_task_context(task_type, None),
830839
),
831840
};
832841

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,22 @@ impl Debug for RawVc {
103103
}
104104
}
105105

106+
impl Display for RawVc {
107+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
108+
match self {
109+
RawVc::TaskOutput(task_id) => write!(f, "output of task {}", **task_id),
110+
RawVc::TaskCell(task_id, cell_id) => {
111+
write!(f, "{} of task {}", cell_id, **task_id)
112+
}
113+
RawVc::LocalOutput(execution_id, local_task_id, task_persistence) => write!(
114+
f,
115+
"output of local task {} ({}, {})",
116+
**local_task_id, **execution_id, task_persistence
117+
),
118+
}
119+
}
120+
}
121+
106122
impl RawVc {
107123
pub fn is_resolved(&self) -> bool {
108124
match self {

0 commit comments

Comments
 (0)