From bf102668bee6b7519ec5ee17f561d3f7be6d9c9e Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 8 Apr 2026 12:06:32 +0100 Subject: [PATCH] gpui: Lazy-init font DB in SvgRenderer to avoid per-test overhead (#53381) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit eaf14d028a6c changed SvgRenderer::new() to eagerly deep-clone the system font database and enrich it with bundled fonts at construction time. Since every #[gpui::test] creates a TestAppContext → App::new_app() → SvgRenderer::new(), and nextest runs each test in its own process, this added ~2-3s of overhead to every GPUI-based test (~132 minutes total across the full suite). Move the expensive work (deep-clone + load_bundled_fonts + fix_generic_font_families) into a OnceLock inside the font resolver closure, so it only executes on the first actual SVG render. Tests that never render SVGs thus do not need to load the fonts which in itself can be fairly expensive. This also bumps the opt-level for crane lift and some other wasmtime crates, as only wasmtime isn't really sufficient Release Notes: - N/A or Added/Fixed/Improved ... --- Cargo.toml | 3 +++ crates/gpui/src/svg_renderer.rs | 26 ++++++++++++++++---------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5a7fc9caaf982953168855671bebbcf4f010df03..925c2d32215a7b6e376d8e203bee5a27faaf2fed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -902,6 +902,9 @@ proc-macro2 = { opt-level = 3 } taffy = { opt-level = 3 } resvg = { opt-level = 3 } wasmtime = { opt-level = 3 } +cranelift-codegen = { opt-level = 3 } +wasmtime-environ = { opt-level = 3 } +wasmtime-internal-cranelift = { opt-level = 3 } # Build single-source-file crates with cg=1 as it helps make `cargo build` of a whole workspace a bit faster activity_indicator = { codegen-units = 1 } assets = { codegen-units = 1 } diff --git a/crates/gpui/src/svg_renderer.rs b/crates/gpui/src/svg_renderer.rs index a766a25cc1ef66039f5b2a1d0aeaab51ace89578..3b5062f55df2a6f31f2b45208ec4edd096b39f8b 100644 --- a/crates/gpui/src/svg_renderer.rs +++ b/crates/gpui/src/svg_renderer.rs @@ -7,7 +7,7 @@ use resvg::tiny_skia::Pixmap; use smallvec::SmallVec; use std::{ hash::Hash, - sync::{Arc, LazyLock}, + sync::{Arc, LazyLock, OnceLock}, }; #[cfg(target_os = "macos")] @@ -111,17 +111,23 @@ impl SvgRenderer { Arc::new(db) }); - let fontdb = { - let mut db = (**SYSTEM_FONT_DB).clone(); - load_bundled_fonts(&*asset_source, &mut db); - fix_generic_font_families(&mut db); - Arc::new(db) - }; + // Build the enriched font DB lazily on first SVG render rather than + // eagerly at construction time. This avoids the expensive deep-clone + // of the system font database for code paths that never render SVGs + // (e.g. tests). + let enriched_fontdb: Arc>> = Arc::new(OnceLock::new()); let default_font_resolver = usvg::FontResolver::default_font_selector(); - let font_resolver = Box::new( + let font_resolver = Box::new({ + let asset_source = asset_source.clone(); move |font: &usvg::Font, db: &mut Arc| { if db.is_empty() { + let fontdb = enriched_fontdb.get_or_init(|| { + let mut db = (**SYSTEM_FONT_DB).clone(); + load_bundled_fonts(&*asset_source, &mut db); + fix_generic_font_families(&mut db); + Arc::new(db) + }); *db = fontdb.clone(); } if let Some(id) = default_font_resolver(font, db) { @@ -135,8 +141,8 @@ impl SvgRenderer { }; db.query(&sans_query) .or_else(|| db.faces().next().map(|f| f.id)) - }, - ); + } + }); let default_fallback_selection = usvg::FontResolver::default_fallback_selector(); let fallback_selection = Box::new( move |ch: char, fonts: &[usvg::fontdb::ID], db: &mut Arc| {