From 5efd0045330104e7c726242b8a7e06d5647c0b7a Mon Sep 17 00:00:00 2001 From: openhands Date: Mon, 24 Aug 2026 18:43:07 +0200 Subject: [PATCH] perf: throttle localized furnidata build to avoid 100% CPU spikes Lower LibreTranslate concurrency to 2 and yield the event loop between languages so the 13x deep-clone + stringify loop no longer pins a core continuously. The build is also already opt-in (off by default on import). --- src/lib/services/furni-data-i18n.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/lib/services/furni-data-i18n.ts b/src/lib/services/furni-data-i18n.ts index 8f8f2cd3..a3683055 100644 --- a/src/lib/services/furni-data-i18n.ts +++ b/src/lib/services/furni-data-i18n.ts @@ -186,7 +186,15 @@ async function translateWithLibre( } const LIBRE_BATCH_SIZE = 48; -const LIBRE_CONCURRENCY = 4; +// Kept low on purpose: the build already pegs a core with the synchronous +// deep-clone + stringify of the 100k+ entry master per language, so we avoid +// spreading onto multiple cores at once. +const LIBRE_CONCURRENCY = 2; +// Breathing room between languages so the event loop (and other CMS requests) +// is never monopolised by the build loop. +const BUILD_YIELD_MS = 150; + +const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms)); /** * Translate many texts in one go using LibreTranslate's array API @@ -463,6 +471,12 @@ export async function buildLocalizedFurniDataFiles( for (const { lang, hotel, map } of maps) { try { + // Yield before each language (except the first) so a long build + // never pins the CPU continuously and the server stays responsive. + if (results.length > 0) { + await new Promise((r) => setImmediate(r)); + await sleep(BUILD_YIELD_MS); + } const cloned = cloneFurniData( master as unknown as Record, );