From 6fa733dc6e4e2ab8f159e157aeb47f73a0f5d5e6 Mon Sep 17 00:00:00 2001 From: BoulderBadgeDad Date: Wed, 3 Jun 2026 08:03:30 -0700 Subject: [PATCH] =?UTF-8?q?Artist=20Map=20v2=20=E2=80=94=20fix=20the=20rea?= =?UTF-8?q?l=20bottleneck:=20cap=20the=20offscreen=20buffer=20(76MP=20?= =?UTF-8?q?=E2=86=92=20~12MP)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Perf telemetry from the genre map (2004 nodes) proved it: the offscreen buffer was 7465×10240 (76 megapixels) — rebuilt in ~979ms on every zoom and blitted at ~150ms/frame (3 fps), with the constellation overlay piling on top. The buffer renders the WHOLE world, and the size cap was 10240px. Cap the max buffer dimension to 4096 (MAX_BUFFER_PX). On the dense genre map that's ~12MP instead of 76MP → ~6x faster rebuild and blit, and more nodes drop under the LOD dot threshold so the rebuild also draws fewer image-clips. The cap only binds on large worlds; small watchlist/explorer maps don't reach it and stay full-resolution. Tunable; perf overlay ('d' → app.log) stays so we can confirm the new numbers. --- webui/static/discover.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/webui/static/discover.js b/webui/static/discover.js index ab244807..4135dbfc 100644 --- a/webui/static/discover.js +++ b/webui/static/discover.js @@ -5004,6 +5004,13 @@ const _artMap = { dirty: true, // true = need to rebuild offscreen buffer WATCHLIST_R: 320, BUFFER: 8, + // Max offscreen-buffer dimension (px). The buffer renders the whole world, + // so on big/dense maps (e.g. 2000-node genre map) this was 10240 → a 76 MP + // canvas that took ~1s to rebuild and ~150ms to blit per frame (3 fps). + // Capping it far lower makes rebuild + blit cheap (and pushes more nodes + // under the LOD dot threshold). Only binds on large worlds — small maps + // stay crisp via the z*2 / 1.0 caps. Tunable. + MAX_BUFFER_PX: 4096, }; async function openArtistMap() { @@ -5348,7 +5355,7 @@ function _artMapRebuildBuffer() { const bh = maxY - minY; // Scale based on zoom — higher zoom = higher res buffer, capped for memory const z = _artMap.zoom || 0.1; - const scale = Math.min(z * 2, 1.0, 10240 / Math.max(bw, bh)); + const scale = Math.min(z * 2, 1.0, _artMap.MAX_BUFFER_PX / Math.max(bw, bh)); if (!_artMap.offscreen) _artMap.offscreen = document.createElement('canvas'); const oc = _artMap.offscreen;