Rate-limit TUI frames from their actual emission time (#39057)

## Why

Recording a late frame's requested deadline as its emission time can leave the
rate limiter with a stale timestamp, allowing the next frame to be emitted
immediately in a redraw burst.

## What changed

Record the current time when the frame scheduler sends a draw notification so
the 120 FPS limit is measured from the actual emission.

## Testing

Add a paused-time regression test that submits an overdue draw and verifies the
next frame waits for `MIN_FRAME_INTERVAL`.

GitOrigin-RevId: 8c9a5ac0bf858b2ad87838f6d7c67c9470fdfc61
This commit is contained in:
Tamir Duberstein
2026-08-17 19:34:05 +00:00
committed by copyberry
parent afb1b3c984
commit 796325f1e5
+34 -1
View File
@@ -118,7 +118,7 @@ impl FrameScheduler {
_ = &mut deadline => {
if next_deadline.is_some() {
next_deadline = None;
self.rate_limiter.mark_emitted(target);
self.rate_limiter.mark_emitted(Instant::now());
let _ = self.draw_tx.send(());
}
}
@@ -275,6 +275,39 @@ mod tests {
assert!(second.is_ok(), "broadcast closed unexpectedly");
}
#[tokio::test(flavor = "current_thread", start_paused = true)]
async fn test_late_draw_still_limits_the_next_frame() {
let (draw_tx, mut draw_rx) = broadcast::channel(16);
let requester = FrameRequester::new(draw_tx);
let delayed_deadline = Instant::now() - MIN_FRAME_INTERVAL.saturating_mul(2);
requester
.frame_schedule_tx
.send(delayed_deadline)
.expect("scheduler should accept the overdue draw");
draw_rx
.recv()
.timeout(Duration::from_millis(50))
.await
.expect("timed out waiting for overdue draw")
.expect("broadcast closed unexpectedly");
requester.schedule_frame();
draw_rx
.recv()
.timeout(Duration::from_millis(1))
.await
.expect_err("a late draw must not trigger a redraw burst");
time::advance(MIN_FRAME_INTERVAL).await;
draw_rx
.recv()
.timeout(Duration::from_millis(50))
.await
.expect("timed out waiting for rate-limited draw")
.expect("broadcast closed unexpectedly");
}
#[tokio::test(flavor = "current_thread", start_paused = true)]
async fn test_rate_limit_clamps_early_delayed_requests() {
let (draw_tx, mut draw_rx) = broadcast::channel(16);