Skip to content

Iteratively diff children and convert array children to Fragments#2507

Merged
marvinhagemeister merged 14 commits intomasterfrom
diffChildren-for-loop
Apr 29, 2020
Merged

Iteratively diff children and convert array children to Fragments#2507
marvinhagemeister merged 14 commits intomasterfrom
diffChildren-for-loop

Conversation

@andrewiggins
Copy link
Copy Markdown
Member

@andrewiggins andrewiggins commented Apr 27, 2020

At the suggestion from @developit from forever ago, this PR no longer uses toChildArray in diffChildren to convert props.children to an array. It also no longer flattens nested arrays when diffing children. It now converts them to Fragments.

I think this change will help us improve diff perf in the future and it also fixes #2446.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 27, 2020

Size Change: +115 B (0%)

Total Size: 39.4 kB

Filename Size Change
dist/preact.js 3.86 kB +28 B (0%)
dist/preact.min.js 3.86 kB +28 B (0%)
dist/preact.module.js 3.88 kB +36 B (0%)
dist/preact.umd.js 3.91 kB +23 B (0%)
ℹ️ View Unchanged
Filename Size Change
compat/dist/compat.js 3.12 kB 0 B
compat/dist/compat.module.js 3.14 kB 0 B
compat/dist/compat.umd.js 3.17 kB 0 B
debug/dist/debug.js 3 kB 0 B
debug/dist/debug.module.js 2.98 kB 0 B
debug/dist/debug.umd.js 3.08 kB 0 B
devtools/dist/devtools.js 185 B 0 B
devtools/dist/devtools.module.js 194 B 0 B
devtools/dist/devtools.umd.js 260 B 0 B
hooks/dist/hooks.js 1.09 kB 0 B
hooks/dist/hooks.module.js 1.11 kB 0 B
hooks/dist/hooks.umd.js 1.17 kB 0 B
test-utils/dist/testUtils.js 437 B 0 B
test-utils/dist/testUtils.module.js 439 B 0 B
test-utils/dist/testUtils.umd.js 515 B 0 B

compressed-size-action

Comment thread src/diff/children.js
// We use `undefined`, as `null` is reserved for empty placeholders
// (holes).
oldVNode = oldChildren[i];
if (childVNode == null || typeof childVNode == 'boolean') {
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This big if statement is the internal VNode coercion that toChildArray did. Terser converts into a massive ternary for us :)

Comment thread src/diff/children.js
export function toChildArray(children, callback, flattened) {
if (flattened == null) flattened = [];

export function toChildArray(children) {
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this function is no longer used in the diff hot path, I rewrote it to optimize for size instead of perf/memory. Let me know what you think. The rewrite saved us about 40 bytes

Comment thread src/diff/children.js
null,
childVNode
);
} else if (Array.isArray(childVNode)) {
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Putting Array.isArray into a utility function added a byte. Using a .pop property check saves us some bytes (~10) but I worry that the property access will quickly de-opt and become megamorphic since it'll sometimes be a VNode and sometimes by an array. So I think imma leave this for now. Can revisit later

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point! iirc checking for .pop() is much slower than Array.isArray() 👍

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep. It used to be the other way around. Not sure about other engines.

https://esbench.com/bench/57f1327e330ab09900a1a1d5

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

firefox

Copy link
Copy Markdown
Member

@JoviDeCroock JoviDeCroock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome, closing my PR. This is some fine work!

Copy link
Copy Markdown
Member

@marvinhagemeister marvinhagemeister left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is top notch! 🥇

@marvinhagemeister marvinhagemeister merged commit 0f8c55c into master Apr 29, 2020
@marvinhagemeister marvinhagemeister deleted the diffChildren-for-loop branch April 29, 2020 18:46
@Jane486

This comment has been minimized.

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 this pull request may close these issues.

Focus displacement when components are added to a list above

6 participants