From 2c88105114b5fde7d757b12062f31d79a2048152 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 29 Oct 2019 15:15:36 +0100 Subject: [PATCH 1/8] child_process,cluster: allow using V8 serialization API Add an `serialization` option that allows child process IPC to use the (typically more powerful) V8 serialization API. Fixes: https://github.com/nodejs/node/issues/10965 --- benchmark/cluster/echo.js | 11 +- doc/api/child_process.md | 36 ++++++ doc/api/cluster.md | 8 ++ doc/api/process.md | 6 + lib/child_process.js | 4 +- lib/internal/bootstrap/pre_execution.js | 6 +- lib/internal/child_process.js | 59 ++++----- lib/internal/child_process/serialization.js | 119 ++++++++++++++++++ lib/internal/cluster/master.js | 1 + node.gyp | 1 + src/stream_base.cc | 18 ++- ...st-child-process-advanced-serialization.js | 46 +++++++ .../test-cluster-advanced-serialization.js | 22 ++++ 13 files changed, 299 insertions(+), 38 deletions(-) create mode 100644 lib/internal/child_process/serialization.js create mode 100644 test/parallel/test-child-process-advanced-serialization.js create mode 100644 test/parallel/test-cluster-advanced-serialization.js diff --git a/benchmark/cluster/echo.js b/benchmark/cluster/echo.js index 73c5971cd41eb2..152f2c42f10f2b 100644 --- a/benchmark/cluster/echo.js +++ b/benchmark/cluster/echo.js @@ -7,16 +7,25 @@ if (cluster.isMaster) { workers: [1], payload: ['string', 'object'], sendsPerBroadcast: [1, 10], + serialization: ['json', 'advanced'], n: [1e5] }); - function main({ n, workers, sendsPerBroadcast, payload }) { + function main({ + n, + workers, + sendsPerBroadcast, + payload, + serialization + }) { const expectedPerBroadcast = sendsPerBroadcast * workers; var readies = 0; var broadcasts = 0; var msgCount = 0; var data; + cluster.settings.serialization = serialization; + switch (payload) { case 'string': data = 'hello world!'; diff --git a/doc/api/child_process.md b/doc/api/child_process.md index 24dd6269f16674..84a6c125cbe71e 100644 --- a/doc/api/child_process.md +++ b/doc/api/child_process.md @@ -321,6 +321,9 @@ arbitrary command execution.** + +Child processes support a serialization mechanism for IPC that is based on the +[serialization API of the `v8` module][v8.serdes]. This is generally more +powerful and supports more built-in JS object types, such as `BigInt`, `Map` +and `Set`, `ArrayBuffer` and `TypedArray`, `Buffer`, `Error`, `RegExp` etc. + +However, this format is not a full superset of JSON, and e.g. properties set on +objects of such built-in types will not be passed on through the serialization +step. Additionally, performance may not be equivalent to that of JSON, depending +on the structure of the passed data. +Therefore, this feature requires opting in by setting the +`serialization` option to `'advanced'` when calling [`child_process.spawn()`][] +or [`child_process.fork()`][]. + +[Advanced Serialization]: #child_process_advanced_serialization [`'disconnect'`]: process.html#process_event_disconnect [`'error'`]: #child_process_event_error [`'exit'`]: #child_process_event_exit @@ -1507,3 +1542,4 @@ unavailable. [Default Windows Shell]: #child_process_default_windows_shell [Shell Requirements]: #child_process_shell_requirements [synchronous counterparts]: #child_process_synchronous_process_creation +[v8.serdes]: v8.html#v8_serialization_api diff --git a/doc/api/cluster.md b/doc/api/cluster.md index 972309a7013690..56f01844c483b7 100644 --- a/doc/api/cluster.md +++ b/doc/api/cluster.md @@ -718,6 +718,9 @@ values are `'rr'` and `'none'`. Child processes support a serialization mechanism for IPC that is based on the -[serialization API of the `v8` module][v8.serdes]. This is generally more -powerful and supports more built-in JavaScript object types, such as `BigInt`, -`Map` and `Set`, `ArrayBuffer` and `TypedArray`, `Buffer`, `Error`, -`RegExp` etc. +[serialization API of the `v8` module][v8.serdes], based on the +[HTML structured clone algorithm][]. This is generally more powerful and +supports more built-in JavaScript object types, such as `BigInt`, `Map` +and `Set`, `ArrayBuffer` and `TypedArray`, `Buffer`, `Error`, `RegExp` etc. However, this format is not a full superset of JSON, and e.g. properties set on objects of such built-in types will not be passed on through the serialization @@ -1542,6 +1542,7 @@ or [`child_process.fork()`][]. [`subprocess.stdout`]: #child_process_subprocess_stdout [`util.promisify()`]: util.html#util_util_promisify_original [Default Windows Shell]: #child_process_default_windows_shell +[HTML structured clone algorithm]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm [Shell Requirements]: #child_process_shell_requirements [synchronous counterparts]: #child_process_synchronous_process_creation [v8.serdes]: v8.html#v8_serialization_api From 73912e22cfa2fc7151d95d4eb1820a50e892f178 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 5 Nov 2019 19:43:56 +0100 Subject: [PATCH 8/8] fixup! child_process,cluster: allow using V8 serialization API Co-Authored-By: Vse Mozhet Byt --- doc/api/child_process.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/child_process.md b/doc/api/child_process.md index a8d50c78087830..a2945ad7647716 100644 --- a/doc/api/child_process.md +++ b/doc/api/child_process.md @@ -1010,7 +1010,7 @@ The `'message'` event is triggered when a child process uses The message goes through serialization and parsing. The resulting message might not be the same as what is originally sent. -If the `serialization` option was set to `advanced` used when spawning the +If the `serialization` option was set to `'advanced'` used when spawning the child process, the `message` argument can contain data that JSON is not able to represent. See [Advanced Serialization][] for more details.