perf(universaldb): time each drain batch statement to localize leader apply stalls - #5706
Conversation
|
Stack for rivet-dev/actors
Get stack: change uzzxusqp |
|
🚅 Deployed to the actors-pr-5706 environment in rivet-frontend
|
| @@ -666,6 +690,23 @@ async fn drain_batch( | |||
| cold_window, | |||
There was a problem hiding this comment.
🟠 Medium · Account for awaited response delivery
batch_ms is measured only after the watermark publish and the for_each_concurrent(... respond(...)) loop, but neither operation has a phase timer. In multi-node mode Responder::respond awaits async_nats::Client::publish, which can block on client backpressure. A slow batch can therefore still have every reported phase near zero, defeating this instrumentation's purpose and contradicting the “sum roughly batch_ms” comment.
Measure these post-commit awaits (at least reply delivery, and ideally watermark publish) or emit the batch timing before them so the remaining time is explicit.
| write_state(&db, start, chunks).await; | ||
| })); | ||
| } | ||
| join_all(handles).await; |
There was a problem hiding this comment.
🔵 Low · Fail the harness when a writer fails
The JoinHandle results are discarded. Since write_state unwraps the transaction result inside its spawned task, any failed or panicked writer only produces a JoinError; this loop continues and prints a partial batch report as if the load completed. That can turn a connection, election, or commit regression into misleading timing output.
Await each handle with unwrap() (or otherwise propagate its error) before reporting.
| #[tokio::test(flavor = "multi_thread", worker_threads = 8)] | ||
| #[ignore] | ||
| async fn leader_apply_wide_table() { | ||
| run_load(8192, 8, 12, 96, "wide table (8192 workflows)").await; |
There was a problem hiding this comment.
🔵 Low · Populate the advertised wide table
Each round writes only concurrency distinct workflows. With 12 rounds and concurrency 96, this scenario visits workflow IDs 0 through 1151 exactly once; the other 7,040 of the advertised 8,192 workflows are never written. The reported range-delete behavior is therefore from a much smaller table than the label and documentation claim.
Increase the rounds/load to populate the intended cardinality, or change the scenario’s cardinality and label to 1,152.
ReviewThis PR adds per-phase timing fields to One finding on the instrumentation's actual coverage, plus a minor style nit. Coverage gap: post-commit work is not in the phase breakdown
The comment on the new fields says the phases "sum to roughly Neither of these is covered by any of the new Nit:
Every other phase follows the pattern of a dedicated Everything else
Generated with Claude Code |
1580368 to
e6540c4
Compare
c040647 to
fb5d946
Compare
| @@ -666,6 +690,23 @@ async fn drain_batch( | |||
| cold_window, | |||
There was a problem hiding this comment.
🟠 Medium · Account for awaited response delivery
batch_ms is measured only after the watermark publish and the for_each_concurrent(... respond(...)) loop, but neither operation has a phase timer. In multi-node mode Responder::respond awaits async_nats::Client::publish, which can block on client backpressure. A slow batch can therefore still have every reported phase near zero, defeating this instrumentation's purpose and contradicting the “sum roughly batch_ms” comment.
Measure these post-commit awaits (at least reply delivery, and ideally watermark publish) or emit the batch timing before them so the remaining time is explicit.
| write_state(&db, start, chunks).await; | ||
| })); | ||
| } | ||
| join_all(handles).await; |
There was a problem hiding this comment.
🔵 Low · Fail the harness when a writer fails
The JoinHandle results are discarded. Since write_state unwraps the transaction result inside its spawned task, any failed or panicked writer only produces a JoinError; this loop continues and prints a partial batch report as if the load completed. That can turn a connection, election, or commit regression into misleading timing output.
Await each handle with unwrap() (or otherwise propagate its error) before reporting.
| #[tokio::test(flavor = "multi_thread", worker_threads = 8)] | ||
| #[ignore] | ||
| async fn leader_apply_wide_table() { | ||
| run_load(8192, 8, 12, 96, "wide table (8192 workflows)").await; |
There was a problem hiding this comment.
🔵 Low · Populate the advertised wide table
Each round writes only concurrency distinct workflows. With 12 rounds and concurrency 96, this scenario visits workflow IDs 0 through 1151 exactly once; the other 7,040 of the advertised 8,192 workflows are never written. The reported range-delete behavior is therefore from a much smaller table than the label and documentation claim.
Increase the rounds/load to populate the intended cardinality, or change the scenario’s cardinality and label to 1,152.
No description provided.