-
-
Notifications
You must be signed in to change notification settings - Fork 35.4k
Move ESM loaders off-thread #44710
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
Move ESM loaders off-thread #44710
Changes from 1 commit
03f6bb4
a0bb205
cd16ccd
01f1191
5f02297
820aa55
231b964
ed412d5
4776a6d
2aed49a
78a2889
5746d17
c1afb3d
666ee10
8198a13
2d39e13
dd6a5d3
1415d6e
a374bd1
98b5512
7be92f3
382753a
2b3e6a5
c73001f
b4cccd4
b272d31
0ec518a
11c1471
0dd5114
d15b425
b796c02
599a616
42d485e
8e3e0c6
76e23d8
75fe62b
350351f
f3b2ed9
7e79b2f
c0142d6
5d7e3b4
685590c
49a4088
d40834d
47bd0bf
17ff524
2065222
b0cc21f
29d019f
8706cbd
04ebc5c
8aae17e
b74dcaa
3312b1c
7e8be7c
7b7e5be
3f4c9bf
140c03b
020b9d7
6899203
9d392ef
1c7dd71
acfa8d9
1821301
b1dcccc
0cfc683
7fd6fa1
a3982ee
47b4d83
d518e53
531c9a3
3bcf18c
b071a89
0911d15
0b1c22b
88686f5
1b1583e
3f4934a
800d151
a5a798b
f9371ae
0b79809
0cfec42
281e943
3e31a1c
595a95f
10bf7b8
106b400
cc9373a
a67af11
aab57d7
638b497
e340d24
018ab18
80cd74c
817d0e8
0590df4
cee03fa
258cf8a
8863cb9
13f3d8d
4731362
12717f7
61ad2a5
fa29a70
159ca6f
b4a8a2f
6177afa
a85288d
be8090e
f6679bc
722fd0e
544bf89
88f9042
6d8bfc6
31e7d5d
372065e
244f916
bc8e970
f44a246
221f2e2
9436c97
ad73db6
95052c6
acc0900
f02012f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
… channel
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -471,9 +471,9 @@ class HooksProxy { | |
| */ | ||
| #lock; | ||
| /** | ||
| * A MessagePort used to synchronously communicate with the worker. | ||
| * The InternalWorker instance, which let us communicate with the loader thread. | ||
| */ | ||
| #syncCommPort; | ||
| #worker; | ||
|
|
||
| #isReady = false; | ||
|
|
||
|
|
@@ -483,30 +483,26 @@ class HooksProxy { | |
|
|
||
| const lock = new SharedArrayBuffer(SHARED_MEMORY_BYTE_LENGTH); | ||
| this.#lock = new Int32Array(lock); | ||
| const syncCommChannel = new MessageChannel(); | ||
| this.#syncCommPort = syncCommChannel.port1; | ||
|
|
||
| const worker = this.worker = new InternalWorker('internal/modules/esm/worker', { | ||
| this.#worker = new InternalWorker('internal/modules/esm/worker', { | ||
| stderr: false, | ||
| stdin: false, | ||
| stdout: false, | ||
|
Comment on lines
+497
to
+499
Member
Author
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. Not related to this PR, but these are so counter-intuitive 😞 |
||
| trackUnmanagedFds: false, | ||
| workerData: { | ||
| lock, | ||
| syncCommPort: syncCommChannel.port2, | ||
| }, | ||
| transferList: [syncCommChannel.port2], | ||
| }); | ||
| worker.unref(); // ! Allows the process to eventually exit. | ||
| this.#worker.unref(); // ! Allows the process to eventually exit. | ||
| } | ||
|
|
||
| #waitForWorker() { | ||
| if (!this.#isReady) { | ||
| const { kIsOnline } = require('internal/worker'); | ||
| if (!this.worker[kIsOnline]) { | ||
| if (!this.#worker[kIsOnline]) { | ||
| debug('wait for signal from worker'); | ||
| AtomicsWait(this.#lock, WORKER_TO_MAIN_THREAD_NOTIFICATION, 0); | ||
| const response = receiveMessageOnPort(this.#syncCommPort); | ||
| const response = this.#worker.receiveMessageSync(); | ||
| const { preloadScripts } = this.#unwrapMessage(response); | ||
| this.#executePreloadScripts(preloadScripts); | ||
| } | ||
|
|
@@ -521,11 +517,11 @@ class HooksProxy { | |
| if (value & WORKER_THREAD_IS_IDLE && AtomicsLoad(this.#lock, NUMBER_OF_MESSAGES_IN_TRANSIT) === 0) { | ||
| debug('send terminate order to worker'); | ||
| // The worker has already reported waiting for us to die together. | ||
| this.worker.terminate(); | ||
| this.#worker.terminate(); | ||
| } else { | ||
| // The worker is still in good health, and we just told it it's the | ||
| // only thing keeping us alive. | ||
| this.worker.ref(); | ||
| this.#worker.ref(); | ||
| } | ||
| }; | ||
|
|
||
|
|
@@ -538,7 +534,7 @@ class HooksProxy { | |
|
|
||
| // Pass work to the worker. | ||
| debug('post async message to worker', { method, args }); | ||
| this.#syncCommPort.postMessage({ method, args, port: asyncCommChannel.port2 }, [asyncCommChannel.port2]); | ||
| this.#worker.postMessage({ method, args, port: asyncCommChannel.port2 }, [asyncCommChannel.port2]); | ||
| // In case the worker was bored, it might lock itself waiting for a signal. | ||
| AtomicsNotify(this.#lock, NUMBER_OF_MESSAGES_IN_TRANSIT); | ||
|
|
||
|
|
@@ -561,13 +557,15 @@ class HooksProxy { | |
| debug('start waiting for async response from worker', { method, args }); | ||
| while (response == null) { | ||
| await AtomicsWaitAsync(this.#lock, WORKER_TO_MAIN_THREAD_NOTIFICATION, 0).value; | ||
| AtomicsAnd(this.#lock, IDLENESS_OF_THREADS, ~MAIN_THREAD_IS_IDLE); // We are no longer bored. | ||
|
|
||
| // In case the beforeExit handler was called during the await, we revert its actions. | ||
| AtomicsAnd(this.#lock, IDLENESS_OF_THREADS, ~MAIN_THREAD_IS_IDLE); | ||
| this.#worker.unref(); | ||
|
|
||
| response = receiveMessageOnPort(asyncCommChannel.port1); | ||
| } | ||
| debug('got async response from worker', { method, args }, this.#lock); | ||
|
|
||
| this.worker.unref(); // We unref the worker here so the beforeExit handler can be called. | ||
| if (AtomicsSub(this.#lock, NUMBER_OF_INCOMING_ASYNC_RESPONSES, 1) <= 1) { | ||
| // We got all the responses from the worker, its job is done (until next time). | ||
| process.off('beforeExit', this.#beforeExitHandler); | ||
|
|
@@ -584,7 +582,7 @@ class HooksProxy { | |
|
|
||
| // Pass work to the worker. | ||
| debug('post sync message to worker', { method, args }); | ||
| this.#syncCommPort.postMessage({ method, args }); | ||
| this.#worker.postMessage({ method, args }); | ||
|
|
||
| // In case the worker was bored, it might lock itself waiting for a signal. | ||
| AtomicsNotify(this.#lock, NUMBER_OF_MESSAGES_IN_TRANSIT); | ||
|
|
@@ -594,7 +592,7 @@ class HooksProxy { | |
| while (response == null) { | ||
| AtomicsWait(this.#lock, WORKER_TO_MAIN_THREAD_NOTIFICATION, 0); // Sleep until worker responds. | ||
|
|
||
| response = receiveMessageOnPort(this.#syncCommPort); | ||
| response = this.#worker.receiveMessageSync(); | ||
|
|
||
| if (response == null && AtomicsLoad(this.#lock, IDLENESS_OF_THREADS) & WORKER_THREAD_IS_IDLE) { | ||
| process.exit(kUnfinishedTopLevelAwait); | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -45,6 +45,7 @@ const { getOptionValue } = require('internal/options'); | |||||||||||||
| const workerIo = require('internal/worker/io'); | ||||||||||||||
| const { | ||||||||||||||
| drainMessagePort, | ||||||||||||||
| receiveMessageOnPort, | ||||||||||||||
| MessageChannel, | ||||||||||||||
| messageTypes, | ||||||||||||||
| kPort, | ||||||||||||||
|
|
@@ -455,10 +456,13 @@ class Worker extends EventEmitter { | |||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| class InternalWorker extends Worker { | ||||||||||||||
|
Member
Author
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. note to self: needs code doc
Member
Author
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.
Suggested change
|
||||||||||||||
|
|
||||||||||||||
| constructor(filename, options) { | ||||||||||||||
| super(filename, options, kIsInternal); | ||||||||||||||
| } | ||||||||||||||
|
aduh95 marked this conversation as resolved.
|
||||||||||||||
|
|
||||||||||||||
| receiveMessageSync() { | ||||||||||||||
| return receiveMessageOnPort(this[kPublicPort]); | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| function pipeWithoutWarning(source, dest) { | ||||||||||||||
|
|
||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.