diff --git a/crates/ui-egui/src/render.rs b/crates/ui-egui/src/render.rs index 98356afb7..f56e6a922 100644 --- a/crates/ui-egui/src/render.rs +++ b/crates/ui-egui/src/render.rs @@ -288,10 +288,28 @@ impl Slot { } } +/// Render workers of an app built by this crate's own tests. Most of them build an app, several +/// run at once, and a test needs a render or two at a time, not the machine's six (issue #3067: +/// sixteen tests at once ran about 96 render threads on 16 cores). A test that needs more asks +/// for them with [`Renderer::with_worker_threads`]. +#[cfg(test)] +pub(crate) const TEST_WORKERS: usize = 2; + +/// Render workers an app starts with: the machine's job-pool size, at most six (none on wasm). +#[cfg(not(test))] +fn default_workers() -> usize { + if cfg!(target_arch = "wasm32") { 0 } else { JobPool::::default_threads().min(6) } +} + +/// Render workers an app starts with in this crate's tests: [`TEST_WORKERS`]. +#[cfg(test)] +fn default_workers() -> usize { + TEST_WORKERS +} + impl Default for Renderer { fn default() -> Self { - let threads = if cfg!(target_arch = "wasm32") { 0 } else { JobPool::::default_threads().min(6) }; - Self::with_worker_threads(threads) + Self::with_worker_threads(default_workers()) } } diff --git a/crates/ui-egui/src/render/thumbnail_tests.rs b/crates/ui-egui/src/render/thumbnail_tests.rs index 2fcd6c5ab..a72ff2e49 100644 --- a/crates/ui-egui/src/render/thumbnail_tests.rs +++ b/crates/ui-egui/src/render/thumbnail_tests.rs @@ -509,6 +509,25 @@ fn a_panicking_render_is_a_failure_not_a_dead_worker() { assert_eq!(app.renderer.live_workers(), workers); } +/// An app built by this crate's tests renders on two workers, not the machine's six: several +/// tests run at once, and each of them used to start six (issue #3067). +#[test] +fn a_test_app_renders_on_two_workers() { + let (mut app, _, ctx) = fixture_with(Session::new(), (*photo()).clone()); + app.renderer.offload = None; // the real job pool + let slot = Slot::Thumb(PhotoId(1)); + let job = app.session.thumb_job(PhotoId(1), 256).unwrap(); + app.renderer.request(slot, job, 30); + assert_eq!(app.renderer.live_workers(), TEST_WORKERS, "the pool starts all its workers with its first job"); + let t0 = std::time::Instant::now(); + while app.renderer.is_pending(slot) { + assert!(t0.elapsed() < std::time::Duration::from_secs(20), "the render never answered"); + std::thread::sleep(std::time::Duration::from_millis(5)); + app.renderer.poll(&ctx, &mut app.session); + } + assert!(app.renderer.textures.contains_key(&slot), "{:?}", app.renderer.failure(slot)); +} + #[test] fn raw_quick_path_frames_build_no_jobs() { // an unedited raw: the grid shows its embedded preview (held here until released) and stops