Skip to content
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

Change default value of ipc to advanced #784

Closed
ehmicky opened this issue Feb 3, 2024 · 2 comments · Fixed by #905
Closed

Change default value of ipc to advanced #784

ehmicky opened this issue Feb 3, 2024 · 2 comments · Fixed by #905

Comments

@ehmicky
Copy link
Collaborator

ehmicky commented Feb 3, 2024

I have done some small research on the difference between the json and the advanced serialization formats of the ipc feature. I just wanted to share them for future reference, so will close this issue.

Speed

Generally speaking, json is ~1.3x faster on small values, while advanced is up to 6x faster faster on big values. This aligns with what the Node.js PR that introduced this feature is benchmarking too. Which is a bit more nuanced than what the documentation is mentioning.

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().

Using my machine (Node 21, Ubuntu 23.10), advanced is:

  • 1.3x slower: on boolean, number, null, short string, empty array, any array with non-random items, empty object
  • same speed: 1KB string, array with 50 random items, object with 10_000 random fields
  • 1.7x faster: object with 1_000_000 random fields
  • 2.5x faster: array with 1_000_000 random items
  • 6x faster: 1MB string

Benchmark code:

import {spawn} from 'node:child_process'
import {once} from 'node:events'

const loopCount = 1e3
const value = '.'.repeat(1e6)

for (const serialization of ['json', 'advanced']) {
  const childProcess = spawn('node', ['child.js'], {stdio: ['pipe', 'pipe', 'pipe', 'ipc'], serialization});
  await once(childProcess, 'message')

  console.time(serialization)
  for (let i = 0; i < loopCount; i += 1) {
    childProcess.send(value)
    await once(childProcess, 'message')
  }
  console.timeEnd(serialization)

  childProcess.disconnect()
}

Compatibility

The documentation mentions that:

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.

I have tried many values of different types. The result is this:

  • advanced keeps regExps, Map, Set, ArrayBuffer, ArrayBufferView, Buffer and Uint8Array as is. Those values are serialized to empty objects with json
  • advanced keeps Date instances as is. Those are serialized to strings with json.
  • advanced supports undefined and bigint, except at the top-level. Those values throw with json.
  • advanced keeps undefined object properties as is. Those properties are filtered out with json.
  • advanced supports NaN, Infinity. Also undefined array items. Those values are serialized to null with json.
  • advanced supports circular references. Those values throw with json.
  • advanced has a generic (not full) support for Error instances. Those values are serialized to empty objects with json.
  • advanced throws if an object/array contains functions or symbols. Those properties are filtered out (but do not error) with json.
  • both formats throw on symbols, functions, promises, proxies, Intl.*
  • both formats ignore symbol keys, setters, getters, property descriptors, inherited properties and non-enumerable properties in objects

So I would personally consider advanced to be mostly a superset of json, which the following caveats:

  • Objects/arrays containing functions, symbols or promises throw with advanced, while they are ignored with json.
  • Objects with toJSON() throw, while they are handled by json
  • Dates are kept as is instead of being converted to strings

I wanted to share this information for any future discussion around that feature.

@ehmicky ehmicky closed this as completed Feb 3, 2024
@ehmicky
Copy link
Collaborator Author

ehmicky commented Mar 11, 2024

@sindresorhus Based on the above, do you think the default value of the serialization option should be json or advanced?

In a nutshell:

  • advanced is slightly slower on small values, but much faster on big values
  • advanced supports many more types. However, it throws on objects/arrays that contain functions (including toJSON()), while json ignores them.

@ehmicky ehmicky reopened this Mar 11, 2024
@sindresorhus
Copy link
Owner

advanced

@ehmicky ehmicky changed the title Small insights about ipc serialization formats Change default value of ipc to advanced Mar 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants