-
-
Notifications
You must be signed in to change notification settings - Fork 31.9k
worker: allow specifying resource limits #26628
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,19 +2,20 @@ | |
|
||
/* global SharedArrayBuffer */ | ||
|
||
const { Object } = primordials; | ||
const { Math, Object } = primordials; | ||
|
||
const EventEmitter = require('events'); | ||
const assert = require('internal/assert'); | ||
const path = require('path'); | ||
|
||
const errorCodes = require('internal/errors').codes; | ||
const { | ||
ERR_WORKER_PATH, | ||
ERR_WORKER_UNSERIALIZABLE_ERROR, | ||
ERR_WORKER_UNSUPPORTED_EXTENSION, | ||
ERR_WORKER_INVALID_EXEC_ARGV, | ||
ERR_INVALID_ARG_TYPE, | ||
} = require('internal/errors').codes; | ||
} = errorCodes; | ||
const { validateString } = require('internal/validators'); | ||
const { getOptionValue } = require('internal/options'); | ||
|
||
|
@@ -37,8 +38,13 @@ const { pathToFileURL } = require('url'); | |
const { | ||
ownsProcessState, | ||
isMainThread, | ||
resourceLimits: resourceLimitsRaw, | ||
threadId, | ||
Worker: WorkerImpl, | ||
kMaxYoungGenerationSizeMb, | ||
kMaxOldGenerationSizeMb, | ||
kCodeRangeSizeMb, | ||
kTotalResourceLimitCount | ||
} = internalBinding('worker'); | ||
|
||
const kHandle = Symbol('kHandle'); | ||
|
@@ -102,7 +108,8 @@ class Worker extends EventEmitter { | |
|
||
const url = options.eval ? null : pathToFileURL(filename); | ||
// Set up the C++ handle for the worker, as well as some internal wiring. | ||
this[kHandle] = new WorkerImpl(url, options.execArgv); | ||
this[kHandle] = new WorkerImpl(url, options.execArgv, | ||
parseResourceLimits(options.resourceLimits)); | ||
if (this[kHandle].invalidExecArgv) { | ||
throw new ERR_WORKER_INVALID_EXEC_ARGV(this[kHandle].invalidExecArgv); | ||
} | ||
|
@@ -113,7 +120,7 @@ class Worker extends EventEmitter { | |
} else if (env !== undefined) { | ||
this[kHandle].setEnvVars(env); | ||
} | ||
this[kHandle].onexit = (code) => this[kOnExit](code); | ||
this[kHandle].onexit = (code, customErr) => this[kOnExit](code, customErr); | ||
this[kPort] = this[kHandle].messagePort; | ||
this[kPort].on('message', (data) => this[kOnMessage](data)); | ||
this[kPort].start(); | ||
|
@@ -157,11 +164,15 @@ class Worker extends EventEmitter { | |
this[kHandle].startThread(); | ||
} | ||
|
||
[kOnExit](code) { | ||
[kOnExit](code, customErr) { | ||
debug(`[${threadId}] hears end event for Worker ${this.threadId}`); | ||
drainMessagePort(this[kPublicPort]); | ||
drainMessagePort(this[kPort]); | ||
this[kDispose](); | ||
if (customErr) { | ||
debug(`[${threadId}] failing with custom error ${customErr}`); | ||
this.emit('error', new errorCodes[customErr]()); | ||
} | ||
this.emit('exit', code); | ||
this.removeAllListeners(); | ||
} | ||
|
@@ -280,6 +291,12 @@ class Worker extends EventEmitter { | |
get stderr() { | ||
return this[kParentSideStdio].stderr; | ||
} | ||
|
||
get resourceLimits() { | ||
if (this[kHandle] === null) return {}; | ||
|
||
return makeResourceLimits(this[kHandle].getResourceLimits()); | ||
} | ||
} | ||
|
||
function pipeWithoutWarning(source, dest) { | ||
|
@@ -294,10 +311,35 @@ function pipeWithoutWarning(source, dest) { | |
dest._maxListeners = destMaxListeners; | ||
} | ||
|
||
const resourceLimitsArray = new Float64Array(kTotalResourceLimitCount); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a reason not to reuse Although if we expose There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Practically speaking, yes, the reason is that |
||
function parseResourceLimits(obj) { | ||
const ret = resourceLimitsArray; | ||
ret.fill(-1); | ||
if (typeof obj !== 'object' || obj === null) return ret; | ||
|
||
if (typeof obj.maxOldGenerationSizeMb === 'number') | ||
ret[kMaxOldGenerationSizeMb] = Math.max(obj.maxOldGenerationSizeMb, 2); | ||
if (typeof obj.maxYoungGenerationSizeMb === 'number') | ||
ret[kMaxYoungGenerationSizeMb] = obj.maxYoungGenerationSizeMb; | ||
if (typeof obj.codeRangeSizeMb === 'number') | ||
ret[kCodeRangeSizeMb] = obj.codeRangeSizeMb; | ||
return ret; | ||
} | ||
|
||
function makeResourceLimits(float64arr) { | ||
return { | ||
maxYoungGenerationSizeMb: float64arr[kMaxYoungGenerationSizeMb], | ||
maxOldGenerationSizeMb: float64arr[kMaxOldGenerationSizeMb], | ||
codeRangeSizeMb: float64arr[kCodeRangeSizeMb] | ||
}; | ||
} | ||
|
||
module.exports = { | ||
ownsProcessState, | ||
isMainThread, | ||
SHARE_ENV, | ||
resourceLimits: | ||
!isMainThread ? makeResourceLimits(resourceLimitsRaw) : {}, | ||
threadId, | ||
Worker, | ||
}; |
Uh oh!
There was an error while loading. Please reload this page.