From 10089300cd8441547e45dfd4f3d078462d114535 Mon Sep 17 00:00:00 2001 From: Ian Clanton-Thuon Date: Tue, 21 Jan 2025 18:10:24 -0800 Subject: [PATCH] Add an option to control the resources available to workers. --- ...workerResourceLimits_2025-01-22-02-09.json | 10 +++++++++ ...workerResourceLimits_2025-01-22-02-09.json | 10 +++++++++ common/reviews/api/module-minifier.api.md | 2 ++ common/reviews/api/worker-pool.api.md | 2 ++ .../module-minifier/src/WorkerPoolMinifier.ts | 16 ++++++++++++-- libraries/worker-pool/src/WorkerPool.ts | 22 ++++++++++++++++--- 6 files changed, 57 insertions(+), 5 deletions(-) create mode 100644 common/changes/@rushstack/module-minifier/add-workerResourceLimits_2025-01-22-02-09.json create mode 100644 common/changes/@rushstack/worker-pool/add-workerResourceLimits_2025-01-22-02-09.json diff --git a/common/changes/@rushstack/module-minifier/add-workerResourceLimits_2025-01-22-02-09.json b/common/changes/@rushstack/module-minifier/add-workerResourceLimits_2025-01-22-02-09.json new file mode 100644 index 00000000000..0f3cf967159 --- /dev/null +++ b/common/changes/@rushstack/module-minifier/add-workerResourceLimits_2025-01-22-02-09.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@rushstack/module-minifier", + "comment": "Add a `workerResourceLimits` option to the `WorkerPoolMinifier` constructor to control the available resources to the workers.", + "type": "minor" + } + ], + "packageName": "@rushstack/module-minifier" +} \ No newline at end of file diff --git a/common/changes/@rushstack/worker-pool/add-workerResourceLimits_2025-01-22-02-09.json b/common/changes/@rushstack/worker-pool/add-workerResourceLimits_2025-01-22-02-09.json new file mode 100644 index 00000000000..7af2d4de718 --- /dev/null +++ b/common/changes/@rushstack/worker-pool/add-workerResourceLimits_2025-01-22-02-09.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@rushstack/worker-pool", + "comment": "Add a `workerResourceLimits` option to the `WorkerPool` constructor to control the available resources to the workers.", + "type": "minor" + } + ], + "packageName": "@rushstack/worker-pool" +} \ No newline at end of file diff --git a/common/reviews/api/module-minifier.api.md b/common/reviews/api/module-minifier.api.md index a412088ee68..b74aba5638a 100644 --- a/common/reviews/api/module-minifier.api.md +++ b/common/reviews/api/module-minifier.api.md @@ -8,6 +8,7 @@ import { MinifyOptions } from 'terser'; import type { RawSourceMap } from 'source-map'; +import type { ResourceLimits } from 'worker_threads'; import type * as WorkerThreads from 'worker_threads'; // @public @@ -79,6 +80,7 @@ export interface IWorkerPoolMinifierOptions { maxThreads?: number; terserOptions?: MinifyOptions; verbose?: boolean; + workerResourceLimits?: ResourceLimits; } // @public diff --git a/common/reviews/api/worker-pool.api.md b/common/reviews/api/worker-pool.api.md index 83d458d5576..1b5a387b8d3 100644 --- a/common/reviews/api/worker-pool.api.md +++ b/common/reviews/api/worker-pool.api.md @@ -6,6 +6,7 @@ /// +import { ResourceLimits } from 'worker_threads'; import { Worker } from 'worker_threads'; // Warning: (ae-internal-missing-underscore) The name "IWorkerPoolOptions" should be prefixed with an underscore because the declaration is marked as @internal @@ -17,6 +18,7 @@ export interface IWorkerPoolOptions { onWorkerDestroyed?: () => void; prepareWorker?: (worker: Worker) => void; workerData?: unknown; + workerResourceLimits?: ResourceLimits; workerScriptPath: string; } diff --git a/libraries/module-minifier/src/WorkerPoolMinifier.ts b/libraries/module-minifier/src/WorkerPoolMinifier.ts index 12945faa946..3e3ee9789db 100644 --- a/libraries/module-minifier/src/WorkerPoolMinifier.ts +++ b/libraries/module-minifier/src/WorkerPoolMinifier.ts @@ -3,6 +3,7 @@ import { createHash } from 'crypto'; import { cpus } from 'os'; +import type { ResourceLimits } from 'worker_threads'; import serialize from 'serialize-javascript'; import type { MinifyOptions } from 'terser'; @@ -36,6 +37,11 @@ export interface IWorkerPoolMinifierOptions { * If true, log to the console about the minification results. */ verbose?: boolean; + + /** + * Optional resource limits for the workers. + */ + workerResourceLimits?: ResourceLimits; } /** @@ -55,7 +61,12 @@ export class WorkerPoolMinifier implements IModuleMinifier { private readonly _activeRequests: Map; public constructor(options: IWorkerPoolMinifierOptions) { - const { maxThreads = cpus().length, terserOptions = {}, verbose = false } = options || {}; + const { + maxThreads = cpus().length, + terserOptions = {}, + verbose = false, + workerResourceLimits + } = options || {}; const activeRequests: Map = new Map(); const resultCache: Map = new Map(); @@ -63,7 +74,8 @@ export class WorkerPoolMinifier implements IModuleMinifier { id: 'Minifier', maxWorkers: maxThreads, workerData: terserOptions, - workerScriptPath: require.resolve('./MinifierWorker') + workerScriptPath: require.resolve('./MinifierWorker'), + workerResourceLimits }); const { version: terserVersion } = require('terser/package.json'); diff --git a/libraries/worker-pool/src/WorkerPool.ts b/libraries/worker-pool/src/WorkerPool.ts index 87b6a9227df..28efb038469 100644 --- a/libraries/worker-pool/src/WorkerPool.ts +++ b/libraries/worker-pool/src/WorkerPool.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See LICENSE in the project root for license information. -import { Worker } from 'worker_threads'; +import { type ResourceLimits, Worker } from 'worker_threads'; /** * Symbol to read the ID off of a worker @@ -38,6 +38,11 @@ export interface IWorkerPoolOptions { * Absolute path to the worker script. */ workerScriptPath: string; + + /** + * Optional resource limits for the workers. + */ + workerResourceLimits?: ResourceLimits; } /** @@ -60,9 +65,18 @@ export class WorkerPool { private readonly _prepare: ((worker: Worker) => void) | undefined; private readonly _workerData: unknown; private readonly _workerScript: string; + private readonly _workerResourceLimits: ResourceLimits | undefined; public constructor(options: IWorkerPoolOptions) { - const { id, maxWorkers, onWorkerDestroyed, prepareWorker, workerData, workerScriptPath } = options; + const { + id, + maxWorkers, + onWorkerDestroyed, + prepareWorker, + workerData, + workerScriptPath, + workerResourceLimits + } = options; this.id = id; this.maxWorkers = maxWorkers; @@ -77,6 +91,7 @@ export class WorkerPool { this._prepare = prepareWorker; this._workerData = workerData; this._workerScript = workerScriptPath; + this._workerResourceLimits = workerResourceLimits; } /** @@ -193,7 +208,8 @@ export class WorkerPool { [WORKER_ID_SYMBOL]?: string; } = new Worker(this._workerScript, { eval: false, - workerData: this._workerData + workerData: this._workerData, + resourceLimits: this._workerResourceLimits }); const id: string = `${this.id}#${++this._nextId}`;