-
-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Single text node hot path #4523
base: main
Are you sure you want to change the base?
Conversation
📊 Tachometer Benchmark ResultsSummaryduration
usedJSHeapSize
Resultscreate10k
duration
usedJSHeapSize
filter-list
duration
usedJSHeapSize
hydrate1k
duration
usedJSHeapSize
many-updates
duration
usedJSHeapSize
replace1k
duration
usedJSHeapSize
run-warmup-0
run-warmup-1
run-warmup-2
run-warmup-3
run-warmup-4
run-final
text-update
duration
usedJSHeapSize
todo
duration
usedJSHeapSize
update10th1k
duration
usedJSHeapSize
|
cd0f32b
to
f5156c4
Compare
Size Change: +420 B (+0.68%) Total Size: 62.5 kB
ℹ️ View Unchanged
|
f5156c4
to
428ac57
Compare
20e7020
to
91f6188
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Re:Andre's comment about the "regression" in replace1k, have you by chance tried giving it more warmup runs? Say bumping up to 25 like a few of the other benches?
That very well might have been in one of your force pushes, just thought I'd ask.
b4f7cfa
to
76a3098
Compare
Looking at the results, the warmup might close the gap a little on average, but not totally: https://github.com/preactjs/preact/actions/runs/11304050028/job/31441949188 Can probably revert/drop that, sorry. Was good to confirm I suppose though. |
e109c40
to
c664014
Compare
📊 Tachometer Benchmark ResultsSummaryduration
usedJSHeapSize
Resultscreate10kduration
usedJSHeapSize
filter-listduration
usedJSHeapSize
hydrate1kduration
usedJSHeapSize
many-updatesduration
usedJSHeapSize
replace1kduration
usedJSHeapSize
run-warmup-0
run-warmup-1
run-warmup-2
run-warmup-3
run-warmup-4
run-final
text-updateduration
usedJSHeapSize
tododuration
usedJSHeapSize
update10th1kduration
usedJSHeapSize
|
20942aa
to
021c18d
Compare
021c18d
to
3bf818a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very impressed with the findings. Really good work!
|
||
newVNode._children = [ | ||
// @ts-expect-error | ||
createVNode(null, (dom.textContent = newChildren), null, null) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might want to consider using dom.appendChild(document.createTextNode(newChildren))
and manually removing previous children. Otherwise, rendering a single text child will blow away non-preact-rendered children from a parent element.
} else if (typeof newChildren === 'string') { | ||
if (newChildren !== oldProps.children) { | ||
while (oldVNode._children && (i = oldVNode._children.pop())) { | ||
// Setting textContent on the dom element will unmount all DOM nodes | ||
// of the previous children, so we don't need to remove DOM in this | ||
// call to unmount | ||
unmount(i, oldVNode, true); | ||
} | ||
|
||
newVNode._children = [ | ||
// @ts-expect-error | ||
createVNode(null, (dom.textContent = newChildren), null, null) | ||
]; | ||
// @ts-expect-error | ||
newVNode._children[0]._dom = dom.firstChild; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
} else if (typeof newChildren === 'string') { | |
if (newChildren !== oldProps.children) { | |
while (oldVNode._children && (i = oldVNode._children.pop())) { | |
// Setting textContent on the dom element will unmount all DOM nodes | |
// of the previous children, so we don't need to remove DOM in this | |
// call to unmount | |
unmount(i, oldVNode, true); | |
} | |
newVNode._children = [ | |
// @ts-expect-error | |
createVNode(null, (dom.textContent = newChildren), null, null) | |
]; | |
// @ts-expect-error | |
newVNode._children[0]._dom = dom.firstChild; | |
} | |
} else if (typeof newChildren === 'string' && typeof oldProps.children === 'string') { | |
if (newChildren !== oldProps.children) { | |
oldVNode._children[0]._dom.data = newChildren; | |
newVNode._children = oldVNode._children; | |
oldVNode._children = []; | |
} |
Supersedes #3939
Similar to 3939 we are seeing some operations take longer as rather than mutating the text-node we'll be swapping positions instead. The impact seems higher in skew based diff though so not sure whether the performance impact will be as high as in 3939.
The replace_1k difference is similar to #3939 (comment)
This could also be problematic with signals as text-updates won't automatically update afaik
Looks like this should not break signals actually
From #2618 we can derive that there are actually a lot of cases where the single child type is a text-node.