From 8061f2267be8ebd66ff29ce7227bf4916ae85657 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Fri, 9 May 2025 17:40:58 +0200 Subject: [PATCH] feat(core): expose opt-in env variable for SSG thread recycling (#11166) --- packages/docusaurus/src/ssg/ssgEnv.ts | 11 +++++++++++ packages/docusaurus/src/ssg/ssgExecutor.ts | 16 +++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/packages/docusaurus/src/ssg/ssgEnv.ts b/packages/docusaurus/src/ssg/ssgEnv.ts index 869be2bca7..b05eba6f93 100644 --- a/packages/docusaurus/src/ssg/ssgEnv.ts +++ b/packages/docusaurus/src/ssg/ssgEnv.ts @@ -27,3 +27,14 @@ export const SSGWorkerThreadTaskSize: number = process.env .DOCUSAURUS_SSG_WORKER_THREAD_TASK_SIZE ? parseInt(process.env.DOCUSAURUS_SSG_WORKER_THREAD_TASK_SIZE, 10) : 10; // TODO need fine-tuning + +// Controls worker thread recycling behavior (maxMemoryLimitBeforeRecycle) +// See https://github.com/facebook/docusaurus/pull/11166 +// See https://github.com/facebook/docusaurus/issues/11161 +export const SSGWorkerThreadRecyclerMaxMemory: number | undefined = process.env + .DOCUSAURUS_SSG_WORKER_THREAD_RECYCLER_MAX_MEMORY + ? parseInt(process.env.DOCUSAURUS_SSG_WORKER_THREAD_RECYCLER_MAX_MEMORY, 10) + : // TODO we should probably provide a default value here + // 2gb is a quite reasonable max that should work well even for large sites + // we'd rather ask community feedback first + undefined; diff --git a/packages/docusaurus/src/ssg/ssgExecutor.ts b/packages/docusaurus/src/ssg/ssgExecutor.ts index 46b9c89fc8..0b4f7c703a 100644 --- a/packages/docusaurus/src/ssg/ssgExecutor.ts +++ b/packages/docusaurus/src/ssg/ssgExecutor.ts @@ -12,7 +12,11 @@ import _ from 'lodash'; import logger, {PerfLogger} from '@docusaurus/logger'; import {createSSGParams} from './ssgParams'; import {renderHashRouterTemplate} from './ssgTemplate'; -import {SSGWorkerThreadCount, SSGWorkerThreadTaskSize} from './ssgEnv'; +import { + SSGWorkerThreadCount, + SSGWorkerThreadRecyclerMaxMemory, + SSGWorkerThreadTaskSize, +} from './ssgEnv'; import {generateHashRouterEntrypoint} from './ssgUtils'; import {createGlobalSSGResult} from './ssgGlobalResult'; import {executeSSGInlineTask} from './ssgWorkerInline'; @@ -124,6 +128,16 @@ const createPooledSSGExecutor: CreateSSGExecutor = async ({ runtime: 'worker_threads', isolateWorkers: false, workerData: {params}, + + // WORKER MEMORY MANAGEMENT + // Allows containing SSG memory leaks with a thread recycling workaround + // See https://github.com/facebook/docusaurus/pull/11166 + // See https://github.com/facebook/docusaurus/issues/11161 + maxMemoryLimitBeforeRecycle: SSGWorkerThreadRecyclerMaxMemory, + resourceLimits: { + // For some reason I can't figure out how to limit memory on a worker + // See https://x.com/sebastienlorber/status/1920781195618513143 + }, }); }, );