Skip to content

Commit cad6d99

Browse files
CaramelFurtargos
authored andcommitted
child_process: speed up 'advanced' ipc receiving
PR-URL: #42931 Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Zeyu "Alex" Yang <himself65@outlook.com>
1 parent a9ab41c commit cad6d99

File tree

1 file changed

+33
-11
lines changed

1 file changed

+33
-11
lines changed

lib/internal/child_process/serialization.js

+33-11
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ const {
44
JSONParse,
55
JSONStringify,
66
StringPrototypeSplit,
7+
ArrayPrototypePush,
8+
ReflectApply,
79
Symbol,
810
TypedArrayPrototypeSubarray,
911
} = primordials;
@@ -13,8 +15,10 @@ const v8 = require('v8');
1315
const { isArrayBufferView } = require('internal/util/types');
1416
const assert = require('internal/assert');
1517
const { streamBaseState, kLastWriteWasAsync } = internalBinding('stream_wrap');
18+
const { readUInt32BE } = require('internal/buffer');
1619

1720
const kMessageBuffer = Symbol('kMessageBuffer');
21+
const kMessageBufferSize = Symbol('kMessageBufferSize');
1822
const kJSONBuffer = Symbol('kJSONBuffer');
1923
const kStringDecoder = Symbol('kStringDecoder');
2024

@@ -51,29 +55,47 @@ class ChildProcessDeserializer extends v8.DefaultDeserializer {
5155
// (aka 'advanced')
5256
const advanced = {
5357
initMessageChannel(channel) {
54-
channel[kMessageBuffer] = Buffer.alloc(0);
58+
channel[kMessageBuffer] = [];
59+
channel[kMessageBufferSize] = 0;
5560
channel.buffering = false;
5661
},
5762

5863
*parseChannelMessages(channel, readData) {
5964
if (readData.length === 0) return;
6065

61-
let messageBuffer = Buffer.concat([channel[kMessageBuffer], readData]);
62-
while (messageBuffer.length > 4) {
63-
const size = messageBuffer.readUInt32BE();
64-
if (messageBuffer.length < 4 + size) {
65-
break;
66-
}
66+
ArrayPrototypePush(channel[kMessageBuffer], readData);
67+
channel[kMessageBufferSize] += readData.length;
68+
69+
// Index 0 should always be present because we just pushed data into it.
70+
let messageBufferHead = channel[kMessageBuffer][0];
71+
while (messageBufferHead.length >= 4) {
72+
// We call `readUInt32BE` manually here, because this is faster than first converting
73+
// it to a buffer and using `readUInt32BE` on that.
74+
const fullMessageSize = ReflectApply(readUInt32BE, messageBufferHead, [0]) + 4;
75+
76+
if (channel[kMessageBufferSize] < fullMessageSize) break;
77+
78+
const concatenatedBuffer = channel[kMessageBuffer].length === 1 ?
79+
channel[kMessageBuffer][0] :
80+
Buffer.concat(
81+
channel[kMessageBuffer],
82+
channel[kMessageBufferSize]
83+
);
6784

6885
const deserializer = new ChildProcessDeserializer(
69-
TypedArrayPrototypeSubarray(messageBuffer, 4, 4 + size));
70-
messageBuffer = TypedArrayPrototypeSubarray(messageBuffer, 4 + size);
86+
TypedArrayPrototypeSubarray(concatenatedBuffer, 4, fullMessageSize)
87+
);
88+
89+
messageBufferHead = TypedArrayPrototypeSubarray(concatenatedBuffer, fullMessageSize);
90+
channel[kMessageBufferSize] = messageBufferHead.length;
91+
channel[kMessageBuffer] =
92+
channel[kMessageBufferSize] !== 0 ? [messageBufferHead] : [];
7193

7294
deserializer.readHeader();
7395
yield deserializer.readValue();
7496
}
75-
channel[kMessageBuffer] = messageBuffer;
76-
channel.buffering = messageBuffer.length > 0;
97+
98+
channel.buffering = channel[kMessageBufferSize] > 0;
7799
},
78100

79101
writeChannelMessage(channel, req, message, handle) {

0 commit comments

Comments
 (0)