From d9906272008a92acd9406ee1628142c8c54c6875 Mon Sep 17 00:00:00 2001 From: Greg Pomerantz Date: Sun, 1 Nov 2026 15:38:22 -0500 Subject: [PATCH] gtauri: distance-from-viewport drop policy for ALL jobs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The backlog must never delay on-screen work. Urgent jobs (real Chromium requests) are now stale-dropped too, not just prefetch: a fast fling queues urgent work for every band it crosses, and all of it except the final band is dead — it filled the queue cap and made fresh on-screen requests wait for the JS retry timer. Safe because the anchor now settles at the final scroll position (trailing send), and on-screen cells have idx >= VPORT so they can never be dropped. A pure LIFO would not fix this: stale jobs sit at the stack bottom, never popped, still blocking the cap. Emulator fling test: 309 stale urgent jobs purged, queue peak 28, all 850 decodable images loaded. --- harnesses/gtauri/src/lib.rs | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/harnesses/gtauri/src/lib.rs b/harnesses/gtauri/src/lib.rs index e5869c6..804121e 100644 --- a/harnesses/gtauri/src/lib.rs +++ b/harnesses/gtauri/src/lib.rs @@ -228,11 +228,13 @@ fn set_prefetch_window(lo: usize, hi: usize) { VPORT.store(lo as u32, Ordering::Relaxed); let mut q = Q.lock().unwrap(); let mut inq = INFLIGHT.lock().unwrap(); - // Stale PREFETCH work (far behind the new viewport) is worthless — drop - // it. URGENT jobs (real pending requests) are never dropped here. + // The anchor just moved to `lo`: everything more than STALE_ROWS + // behind it is dead work (urgent included — a fling leaves urgent + // jobs for every band it crossed). Drop it instantly so it can never + // delay the new viewport or eat queue capacity. let kept = q.len(); q.retain(|j| { - if j.urgent || j.idx + STALE_ROWS >= lo as u32 { + if j.idx + STALE_ROWS >= lo as u32 { return true; } inq.remove(&j.id); @@ -269,14 +271,21 @@ fn pop_next() -> Job { g = Q_CV.wait(g).unwrap(); continue; } - // Only PREFETCH work is droppable. URGENT jobs are real pending - // requests (JS/Chromium is waiting on them) — even if the viewport - // anchor went stale, they must run. + // Distance-from-viewport policy: any job more than STALE_ROWS + // behind the viewport is dead work — the user flung past it, and + // decoding it would only delay what is actually on screen. This + // applies to URGENT jobs too (a fling queues urgent work for every + // band it crosses; all of it except the final band is stale). Safe + // because the anchor now always settles at the final scroll + // position (trailing send), and on-screen cells have idx >= VPORT + // so they can never be dropped. (A pure LIFO would not solve this: + // the stale pile sits at the stack bottom, never popped, still + // blocking the queue cap.) if let Some(j) = g.front() { - if !j.urgent && j.idx + STALE_ROWS < VPORT.load(Ordering::Relaxed) { + if j.idx + STALE_ROWS < VPORT.load(Ordering::Relaxed) { let j = g.pop_front().unwrap(); INFLIGHT.lock().unwrap().remove(&j.id); - tr(&format!("drop stale id={} idx={}", j.id, j.idx)); + tr(&format!("drop stale id={} idx={} urgent={}", j.id, j.idx, j.urgent)); continue; } }