unlock unlimited code runs for $79, limited time →
NOSSLETTER.techLIVE
back to OSSpedia
data-structureserror-handling

[Perf Tracks] Don't enumerate typed array props in dev

Project: facebook/react | Language: JavaScript | Concepts: data-structures, error-handling | Difficulty: mid
Link: https://github.com/react/react/pull/36913

The problem

When passing a large TypedArray (like Float32Array(25000000)) as a prop in development mode, React's performance tracking code would freeze the page. This happened because the code tried to enumerate all properties of the TypedArray using a for...in loop, which forces the JS engine to create a string key for every index—even if the loop breaks after a few iterations. This made rendering unusably slow for large arrays.

Why it's non-trivial

A naive fix would be to simply break the enumeration after a certain number of properties (as was already done with OBJECT_WIDTH_LIMIT). However, with TypedArrays, the engine still eagerly creates keys for every index before the loop body runs, so the early break does not help performance. The solution needs to avoid enumeration entirely for these objects.

The approach

1. Skip enumeration for TypedArrays in property listing:

+  if (ArrayBuffer.isView(object)) {
+    // Typed arrays (e.g. Uint8Array, Float32Array) can hold millions of
+    // elements. Enumerating them with for...in forces the engine to
+    // materialize a key for every index, which can freeze the page. Their
+    // contents aren't useful to show here so we skip them. DataView has no
+    // enumerable properties to show anyway.
+    return;
+  }
  • This guard is added at the start of addObjectToProperties. If the object is a TypedArray (anything for which ArrayBuffer.isView is true), the function returns early and does not enumerate its properties. This prevents the expensive enumeration step entirely.

2. Show a compact descriptor for TypedArrays instead of their contents:

+        if (ArrayBuffer.isView(value)) {
+          // Typed arrays can hold millions of elements. Showing the type and
+          // length is more useful than enumerating every index (which is also
+          // prohibitively slow, see addObjectToProperties). DataView is the
+          // only view without a length; show just its type.
+          const length = (value as any).length;
+          desc =
+            typeof length === 'number'
+              ? objectName + '(' + length + ')'
+              : objectName;
+          break;
+        }
  • In addValueToProperties, if the value is a TypedArray, it sets the descriptor to something like Float32Array(1000), showing the type and length, instead of listing all elements. This is both fast and more informative.

3. Update and add tests to reflect the new behavior:

-                ['+   buffer', 'Uint8Array'],
-                ['+     0', '0'],
-                ['+     1', '0'],
-                ...
-                ['+     99', '0'],
-                [
-                  '+     Only 100 properties are shown. React will not log more properties of this object.',
-                  '',
-                ],
+                ['+   buffer', 'Uint8Array(1000)'],
  • The test that previously expected the first 100 entries of a TypedArray to be listed is updated to expect just the compact type/length descriptor.

A new test is also added to verify that for a TypedArray prop, React shows only the type and length, not the enumerated values.

From the review thread

[review] eps1lon: Why change this? The assertions should be updated instead to show the new behavior.

[review] eps1lon: Why do we need the object.length check?

Takeaways

  • Avoid property enumeration on objects with potentially huge numbers of enumerable properties (like TypedArrays); check the type up front and handle specially if needed.
  • Early returns for special cases can prevent expensive operations that are triggered before the loop body (such as property key materialization in for...in on TypedArrays).
  • When displaying debug or log output for large data structures, prefer concise summaries (type and size) over detailed listings that could degrade performance or overwhelm the user.