0

In a high-performance Node.js service, I noticed that structuredClone() introduces unexpected latency spikes when cloning large nested objects (30–50 KB each). Even switching to manual cloning strategies didn’t consistently improve performance.

Example:

const cloned = structuredClone(largeData);

Profiling in Chrome DevTools shows a lot of time spent in CloneObject and Serialize/Deserialize phases.

My questions for experienced developers:

  1. Why does structuredClone() sometimes perform worse than optimized manual cloning for large hierarchical data?

  2. Does the JavaScript engine (V8) allocate new hidden classes for cloned objects?

  3. Are there recommended patterns for cloning "hot path" data structures without causing GC pressure?

  4. For large objects, is it better to restructure the data model instead of cloning?

Looking for answers based on real-world performance tuning, not textbook explanations.

4
  • 'introduces unexpected latency spikes' sounds like garbage collection is getting called a lot. Can objects once created be reused? Commented Nov 21 at 17:01
  • or even re-use stub sub-objects, so you're not de-opting every property addition. also, nested entries-like arrays might be better if you're doing a lot of object modification. Commented Nov 21 at 17:12
  • "Using structuredClone()" and "high-performance" are two concepts that don't go together very well in my head. Generally, I strive very hard to avoid ever having to deep-copy objects. Seems to me like you have an algorithmic/data-structure problem and not a tooling problem. Commented Nov 22 at 16:33
  • 1
    @Pointy Agreed, but if someone was told that immutable state is good, and not made aware that copying large amounts of state is costly, then this question documents an important step on the learning journey :-) Commented Nov 23 at 14:00

1 Answer 1

4
  1. Why does structuredClone() sometimes perform worse than optimized manual cloning for large hierarchical data?

Node.js's structuredClone() reuses V8's implementation of object serialization/deserialization, so it first writes the input object into an internal serialized format, and then deserializes that data to create the result object. That's not exactly the fastest way to implement object cloning.
(But on the bright side, it avoids having to build a relatively complicated alternative implementation, and it provides the nice guarantee that the behavior will be the same as for other related operations, such as postMessage()ing an object to a worker.)

  1. Does the JavaScript engine (V8) allocate new hidden classes for cloned objects?

No. When suitable hidden classes exist already, they are reused. There's even a fast path that specifically targets this situation.

  1. Are there recommended patterns for cloning "hot path" data structures without causing GC pressure?

Cloning objects means allocating new objects, which is probably what you mean by "GC pressure". If you don't want that, then don't create new objects.
Don't expect cloning to be faster than creating a new object of the same size/structure.

  1. For large objects, is it better to restructure the data model instead of cloning?

The definition of "better" depends on your requirements. Cloning large nested object structures will always be a relatively costly operation; avoiding that will usually yield a performance benefit (but of course that depends on the specific alternative you choose).

Personally I would choose modifiable state over cloned objects in almost all cases, especially if the objects are big, for performance reasons. But I'm aware that some programming paradigms have other priorities, and that's cool too if it works for you.

Sign up to request clarification or add additional context in comments.

2 Comments

"When suitable hidden classes exist already, they are reused. There's even a fast path that specifically targets this situation"- I'm not totally sure what the OP meant by that, can you clarify what you did?
Here's the fast path that uses transitions between existing hidden classes (internally called "maps"): source.chromium.org/chromium/chromium/src/+/main:v8/src/objects/… . If you don't know what a hidden class is, see v8.dev/docs/hidden-classes, or simply don't worry about it.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.