From 3ca9e653a6641c3bd9b065e38275533567fdfa87 Mon Sep 17 00:00:00 2001 From: rubikscraft Date: Wed, 15 Jun 2022 17:41:43 +0200 Subject: [PATCH] child_process: improve ipc write performance PR-URL: https://github.com/nodejs/node/pull/42931 Reviewed-By: Ruben Bridgewater Reviewed-By: Luigi Pinca Reviewed-By: Zeyu "Alex" Yang --- lib/internal/child_process/serialization.js | 34 +++++++++++++-------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/lib/internal/child_process/serialization.js b/lib/internal/child_process/serialization.js index f8b919ba300179..497bf233d77897 100644 --- a/lib/internal/child_process/serialization.js +++ b/lib/internal/child_process/serialization.js @@ -5,7 +5,6 @@ const { JSONStringify, StringPrototypeSplit, ArrayPrototypePush, - ReflectApply, Symbol, TypedArrayPrototypeSubarray, } = primordials; @@ -15,7 +14,6 @@ const v8 = require('v8'); const { isArrayBufferView } = require('internal/util/types'); const assert = require('internal/assert'); const { streamBaseState, kLastWriteWasAsync } = internalBinding('stream_wrap'); -const { readUInt32BE } = require('internal/buffer'); const kMessageBuffer = Symbol('kMessageBuffer'); const kMessageBufferSize = Symbol('kMessageBufferSize'); @@ -71,7 +69,12 @@ const advanced = { while (messageBufferHead.length >= 4) { // We call `readUInt32BE` manually here, because this is faster than first converting // it to a buffer and using `readUInt32BE` on that. - const fullMessageSize = ReflectApply(readUInt32BE, messageBufferHead, [0]) + 4; + const fullMessageSize = ( + messageBufferHead[0] << 24 | + messageBufferHead[1] << 16 | + messageBufferHead[2] << 8 | + messageBufferHead[3] + ) + 4; if (channel[kMessageBufferSize] < fullMessageSize) break; @@ -100,20 +103,27 @@ const advanced = { writeChannelMessage(channel, req, message, handle) { const ser = new ChildProcessSerializer(); + // Add 4 bytes, to later populate with message length + ser.writeRawBytes(Buffer.allocUnsafe(4)); ser.writeHeader(); ser.writeValue(message); + const serializedMessage = ser.releaseBuffer(); - const sizeBuffer = Buffer.allocUnsafe(4); - sizeBuffer.writeUInt32BE(serializedMessage.length); - - const buffer = Buffer.concat([ - sizeBuffer, - serializedMessage, - ]); - const result = channel.writeBuffer(req, buffer, handle); + const serializedMessageLength = serializedMessage.length - 4; + + serializedMessage.set([ + serializedMessageLength >> 24 & 0xFF, + serializedMessageLength >> 16 & 0xFF, + serializedMessageLength >> 8 & 0xFF, + serializedMessageLength & 0xFF, + ], 0); + + const result = channel.writeBuffer(req, serializedMessage, handle); + // Mirror what stream_base_commons.js does for Buffer retention. if (streamBaseState[kLastWriteWasAsync]) - req.buffer = buffer; + req.buffer = serializedMessage; + return result; }, };