react icon indicating copy to clipboard operation
react copied to clipboard

Optimizing Compiler: Tagging ReactElements

Open sebmarkbage opened this issue 10 years ago • 7 comments

We can make more optimized reconciliation by tagging ReactElements with the "hidden class" of their props.

For example, this is guaranteed to always have three props: className, width, children.

<div className="foo" style={{ width: w, height: 100 }}>{c}</div>

If we could tag every element with these properties with a unique ID:

{ __t: 7, type: 'div', props: { className: 'foo', style: { width: w, height: 5 }, children: c } }

Then we could use the hidden class to generate an optimized diffing algorithm for these instead of iterating over the properties. Presumably, we would only need to do this for type: <string> since we only diff native components.

Bonus points if we can determine which properties are constant. Perhaps using a property descriptor object:

// Constant properties are annotated as 1, other properties are excluded and inferred by props.
var t = { className: 1, style: { height: 1 } };
{ __t: t, type: 'div', props: { className: 'foo', style: { width: w, height: 5 }, children: c } }

We would use a heuristic inside React to determine when to create an optimized differ. For example, after 10+ updates to the same component. Just like a JIT would do.

if (oldElement.__t === newElement.__t) {
  numberOfUpdates++;
} else {
  numberOfUpdates = 0;
}

if (numberOfUpdates === 10) {
  optimizedDiffer = generateOptimizedDiffer(newElement);
  optimizedDiffer(oldElement, newElement);
} else if (numberOfUpdates > 10) {
  optimizedDiffer(oldElement, newElement);
} else {
  manualDiffing(oldElement, newElement);
}

sebmarkbage avatar Feb 22 '15 03:02 sebmarkbage

If we could tag every element with these properties with a unique ID:

This seems problematic with watcher builds and generally keeping bundle hashes static for production. Or is this intended to be a production build post-process of some sort? But even then there are problems when separate parts of apps are built/maintained individually.

Then we could use the hidden class to generate an optimized diffing algorithm for these instead of iterating over the properties. Presumably, we would only need to do this for type: since we only diff native components.

This would be very useful for non-DOM elements too I would think (but it would have to be opt-in).

Bonus points if we can determine which properties are constant. Perhaps using a property descriptor object:

It seems to me that you would also want __ts to reference a shared unique ID which would identify the unique set of actual props to check or you'll end up with a potential of O(2^n) differs rather than O(n), n being unique sets of prop names to check.

We would use a heuristic inside React to determine when to create an optimized differ. For example, after 10+ updates to the same component. Just like a JIT would do.

Shouldn't this be globally per __t rather than per instance?

syranide avatar Feb 23 '15 13:02 syranide

cc @jimfb

sophiebits avatar Aug 28 '15 21:08 sophiebits

@sebmarkbage why not instead use the hidden class object to reference props that are dynamic rather than static ones?

var t = { children: 1, style: { width: 1 } };
{ __t: t, type: 'div', props: { className: 'foo', style: { width: w, height: 5 }, children: c } }

Then you'd easily be able to loop through only these props upon doing a patch of the ReactElement.

You could go one step further (would affect backwards compatibility) and make the original ReactElement only return dynamic props plus the hidden class reference. The hidden class would reference all the static props.

Furthermore, you can work out what is static at compile time, depending on how much computation time you want to spend in the compilation stage, for example the following would return as static:

'someString' 1 + 1 foo + 'bar' (given foo is a const)

There are plenty more too, but those are the easy ones to find in the AST.

trueadm avatar Jan 22 '16 20:01 trueadm

@trueadm I think @sebmarkbage mentioned that originally with "Bonus points if we can determine which properties are constant.".

sophiebits avatar Jan 22 '16 20:01 sophiebits

@spicyj wasn't that referring to the hidden class only referencing props that were constant/static? Sorry, maybe I misunderstood what point of mine you were referencing.

trueadm avatar Jan 22 '16 20:01 trueadm

Oh, I totally misread. You're right, my apologies.

sophiebits avatar Jan 22 '16 20:01 sophiebits

yes, it makes compiler to quickly intrepret the code and this would be optimistic solution for avoiding compiling overhead

No12ah-a avatar May 18 '25 13:05 No12ah-a