Skip to content

Link/cut tree for internal DomSlot for faster traversal - #4189

Open
WorldSEnder wants to merge 18 commits into
yewstack:masterfrom
WorldSEnder:cut-link-dom-position
Open

Link/cut tree for internal DomSlot for faster traversal#4189
WorldSEnder wants to merge 18 commits into
yewstack:masterfrom
WorldSEnder:cut-link-dom-position

Conversation

@WorldSEnder

Copy link
Copy Markdown
Member

Description

This prepares a change in the structure to a link/cut tree. We want clear ownership rules, where each DynamicDomSlot owns an internal node, the clones are only handles for it, but should not keep the slot alive.

Checklist

  • I have reviewed my own code
  • I have added tests

@WorldSEnder WorldSEnder changed the title remove Clone impl from DomPosition Link/cut tree for internal DomSlot for faster traversal Jul 22, 2026
@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown

Visit the preview URL for this PR (updated for commit ccea9a3):

https://yew-rs-api--pr4189-cut-link-dom-positio-xow3l9s4.web.app

(expires Thu, 27 Aug 2026 12:55:18 GMT)

🔥 via Firebase Hosting GitHub Action 🌎

@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown

Benchmark - core

Yew Master

vnode           fastest       │ slowest       │ median        │ mean          │ samples │ iters
╰─ vnode_clone  2.749 ns      │ 2.837 ns      │ 2.752 ns      │ 2.756 ns      │ 100     │ 1000000000

Pull Request

vnode           fastest       │ slowest       │ median        │ mean          │ samples │ iters
╰─ vnode_clone  2.673 ns      │ 3.459 ns      │ 2.678 ns      │ 2.689 ns      │ 100     │ 1000000000

@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown

Benchmark - SSR

Yew Master

Details
Benchmark Round Min (ms) Max (ms) Mean (ms) Standard Deviation
Baseline 10 346.737 347.035 346.841 0.087
Hello World 10 480.504 504.017 484.511 7.168
Function Router 10 33461.402 33645.639 33566.148 55.818
Concurrent Task 10 1006.368 1007.834 1007.133 0.584
Many Providers 10 1025.394 1068.774 1043.238 14.862

Pull Request

Details
Benchmark Round Min (ms) Max (ms) Mean (ms) Standard Deviation
Baseline 10 346.656 347.106 346.863 0.156
Hello World 10 469.556 498.282 483.181 10.825
Function Router 10 33454.274 33776.846 33621.368 105.541
Concurrent Task 10 1006.127 1007.942 1007.151 0.555
Many Providers 10 1005.470 1057.635 1023.878 16.384

This prepares a change in the structure to a link/cut tree.
We want clear ownership rules, where each DynamicDomSlot
owns an internal node, the clones are only handles for it, but
should not keep the slot alive.
@WorldSEnder
WorldSEnder force-pushed the cut-link-dom-position branch from d94d1b5 to 7e99014 Compare July 22, 2026 10:38
@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown

Size Comparison

Details
examples master (KB) pull request (KB) diff (KB) diff (%)
async_clock 100.214 101.748 +1.534 +1.531%
boids 164.948 166.442 +1.494 +0.906%
communication_child_to_parent 93.719 95.175 +1.456 +1.554%
communication_grandchild_with_grandparent 106.002 107.471 +1.469 +1.386%
communication_grandparent_to_grandchild 102.321 103.780 +1.459 +1.426%
communication_parent_to_child 91.105 92.559 +1.453 +1.595%
contexts 106.313 107.687 +1.373 +1.292%
counter 86.279 87.806 +1.526 +1.769%
counter_functional 88.311 89.837 +1.526 +1.728%
dyn_create_destroy_apps 90.178 91.667 +1.489 +1.651%
file_upload 98.587 100.120 +1.533 +1.555%
function_delayed_input 94.624 96.150 +1.526 +1.613%
function_memory_game 168.594 169.938 +1.345 +0.798%
function_router 400.071 400.920 +0.849 +0.212%
function_todomvc 164.995 166.400 +1.405 +0.852%
futures 235.957 237.491 +1.534 +0.650%
game_of_life 100.631 102.157 +1.526 +1.517%
immutable 258.564 260.408 +1.844 +0.713%
inner_html 80.789 82.321 +1.532 +1.897%
js_callback 109.763 111.206 +1.443 +1.315%
keyed_list 176.352 177.809 +1.457 +0.826%
mount_point 84.201 85.733 +1.532 +1.820%
nested_list 112.729 114.194 +1.465 +1.299%
node_refs 91.784 93.240 +1.456 +1.586%
password_strength 1765.991 1767.486 +1.495 +0.085%
portals 93.606 95.086 +1.479 +1.581%
router 366.301 367.223 +0.922 +0.252%
suspense 113.945 115.324 +1.379 +1.210%
timer 88.525 90.079 +1.554 +1.755%
timer_functional 99.431 100.951 +1.521 +1.529%
todomvc 141.994 143.520 +1.525 +1.074%
two_apps 86.184 87.710 +1.526 +1.771%
web_worker_fib 136.489 137.970 +1.480 +1.085%
web_worker_prime 186.590 188.070 +1.480 +0.793%
webgl 82.936 84.470 +1.534 +1.850%

⚠️ The following examples have changed their size significantly:

examples master (KB) pull request (KB) diff (KB) diff (%)
async_clock 100.214 101.748 +1.534 +1.531%
communication_child_to_parent 93.719 95.175 +1.456 +1.554%
communication_grandchild_with_grandparent 106.002 107.471 +1.469 +1.386%
communication_grandparent_to_grandchild 102.321 103.780 +1.459 +1.426%
communication_parent_to_child 91.105 92.559 +1.453 +1.595%
contexts 106.313 107.687 +1.373 +1.292%
counter 86.279 87.806 +1.526 +1.769%
counter_functional 88.311 89.837 +1.526 +1.728%
dyn_create_destroy_apps 90.178 91.667 +1.489 +1.651%
file_upload 98.587 100.120 +1.533 +1.555%
function_delayed_input 94.624 96.150 +1.526 +1.613%
game_of_life 100.631 102.157 +1.526 +1.517%
inner_html 80.789 82.321 +1.532 +1.897%
js_callback 109.763 111.206 +1.443 +1.315%
mount_point 84.201 85.733 +1.532 +1.820%
nested_list 112.729 114.194 +1.465 +1.299%
node_refs 91.784 93.240 +1.456 +1.586%
portals 93.606 95.086 +1.479 +1.581%
suspense 113.945 115.324 +1.379 +1.210%
timer 88.525 90.079 +1.554 +1.755%
timer_functional 99.431 100.951 +1.521 +1.529%
todomvc 141.994 143.520 +1.525 +1.074%
two_apps 86.184 87.710 +1.526 +1.771%
web_worker_fib 136.489 137.970 +1.480 +1.085%
webgl 82.936 84.470 +1.534 +1.850%

@WorldSEnder

Copy link
Copy Markdown
Member Author

@Madoshakalaka the cut tree forest impl is a bit dense. Apart from that, I am not so sure the code size costs are worth the performance. It should definitely save a bit of time in deeply nested things and I want to perf check this before a final judgement too. Thoughts?

@Madoshakalaka

Copy link
Copy Markdown
Member

wut, will have a look tomorrow!

@WorldSEnder

Copy link
Copy Markdown
Member Author

Removing the slab and going back to Rcs could be an avenue to remove a bit of bytes from the code section again. But I already dread borrowing and cloning these everywhere.

@WorldSEnder WorldSEnder added performance A-yew Area: The main yew crate labels Aug 19, 2026
@WorldSEnder

Copy link
Copy Markdown
Member Author

@Madoshakalaka 1kB of overhead cut by going back to "just" an Rc. There might be more things to cut. Downside is there is now a bit of unsafe code. Do you have time to give a quick review? Even telling me where more comments are needed would be appreciated.

I have a (silly) worst-case example benchmark where this gains quite a bit of performance, not included in the PR though. I will run the benchmarks in the repo locally, since the CI fails to build them.

repo currently contains a peerDependency
on esLint that can't be fulfilled. Accept esLint
^10 with --legacy-peer-deps
@WorldSEnder

WorldSEnder commented Aug 20, 2026

Copy link
Copy Markdown
Member Author

The benchmark numbers are looking incredibly good on CI, I can't reproduce this on my laptop.

@WorldSEnder
WorldSEnder marked this pull request as ready for review August 20, 2026 13:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-yew Area: The main yew crate performance

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants