Skip to content
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

Make Html (VNode) cheap to clone #3431

Merged
merged 31 commits into from
Oct 27, 2023
Merged

Conversation

cecton
Copy link
Member

@cecton cecton commented Sep 30, 2023

Description

I tried to do this change a few times this year but couldn't make it works.
There was always something blocking me somewhere in the code that was just too
complicated to solve. But now, it seems that Yew has evolved so much that this
change is now easy to do! [edit: actually it wasn't 😓] I'm really happy about it.

I'm not gonna explain the whole thing again. Please refer to the discussion.

Related to #3022

Checklist

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

@github-actions
Copy link

github-actions bot commented Sep 30, 2023

Size Comparison

examples master (KB) pull request (KB) diff (KB) diff (%)
async_clock 104.058 103.356 -0.701 -0.674%
boids 176.885 177.007 +0.122 +0.069%
communication_child_to_parent 96.438 96.092 -0.347 -0.359%
communication_grandchild_with_grandparent 110.166 109.188 -0.978 -0.887%
communication_grandparent_to_grandchild 106.829 105.545 -1.284 -1.202%
communication_parent_to_child 93.911 93.432 -0.479 -0.511%
contexts 114.539 112.849 -1.690 -1.476%
counter 90.319 90.120 -0.199 -0.221%
counter_functional 91.052 90.788 -0.264 -0.290%
dyn_create_destroy_apps 93.488 93.336 -0.152 -0.163%
file_upload 104.776 104.507 -0.270 -0.257%
function_memory_game 175.780 175.767 -0.014 -0.008%
function_router 355.793 354.042 -1.751 -0.492%
function_todomvc 164.587 164.445 -0.142 -0.086%
futures 229.140 232.297 +3.157 +1.378%
game_of_life 113.382 113.299 -0.083 -0.073%
immutable 189.830 190.524 +0.694 +0.366%
inner_html 87.096 86.324 -0.771 -0.886%
js_callback 114.514 114.036 -0.478 -0.417%
keyed_list 202.075 202.916 +0.841 +0.416%
mount_point 90.317 89.444 -0.873 -0.967%
nested_list 116.955 117.034 +0.079 +0.068%
node_refs 97.415 97.145 -0.271 -0.278%
password_strength 1754.902 1754.218 -0.685 -0.039%
portals 99.504 98.315 -1.188 -1.194%
router 321.744 321.604 -0.140 -0.043%
simple_ssr 145.226 144.829 -0.396 -0.273%
ssr_router 393.559 392.061 -1.498 -0.381%
suspense 120.174 120.247 +0.073 +0.061%
timer 92.914 92.680 -0.234 -0.252%
timer_functional 101.622 101.456 -0.166 -0.163%
todomvc 144.908 144.585 -0.323 -0.223%
two_apps 91.026 90.246 -0.780 -0.857%
web_worker_fib 140.201 139.053 -1.148 -0.819%
web_worker_prime 191.812 189.807 -2.005 -1.045%
webgl 89.669 88.929 -0.740 -0.826%

⚠️ The following examples have changed their size significantly:

examples master (KB) pull request (KB) diff (KB) diff (%)
communication_grandparent_to_grandchild 106.829 105.545 -1.284 -1.202%
contexts 114.539 112.849 -1.690 -1.476%
futures 229.140 232.297 +3.157 +1.378%
portals 99.504 98.315 -1.188 -1.194%
web_worker_prime 191.812 189.807 -2.005 -1.045%

@github-actions
Copy link

github-actions bot commented Sep 30, 2023

Benchmark - SSR

Yew Master

Benchmark Round Min (ms) Max (ms) Mean (ms) Standard Deviation
Baseline 10 356.463 360.993 358.455 1.310
Hello World 10 621.578 626.818 622.766 1.675
Function Router 10 2109.445 2119.982 2115.930 3.978
Concurrent Task 10 1007.389 1008.839 1008.203 0.476
Many Providers 10 1464.889 1483.306 1473.422 6.645

Pull Request

Benchmark Round Min (ms) Max (ms) Mean (ms) Standard Deviation
Baseline 10 319.285 321.955 319.712 0.803
Hello World 10 649.651 658.244 652.310 2.337
Function Router 10 2130.727 2139.741 2135.265 3.006
Concurrent Task 10 1006.466 1008.981 1008.284 0.718
Many Providers 10 1466.062 1492.056 1473.267 7.778

@github-actions
Copy link

github-actions bot commented Sep 30, 2023

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

https://yew-rs-api--pr3431-html-cheap-to-clone-fnap4qt0.web.app

(expires Fri, 03 Nov 2023 13:58:49 GMT)

🔥 via Firebase Hosting GitHub Action 🌎

@cecton cecton marked this pull request as ready for review September 30, 2023 13:01
github-actions[bot]
github-actions bot previously approved these changes Sep 30, 2023
github-actions[bot]
github-actions bot previously approved these changes Sep 30, 2023
Copy link
Member

@futursolo futursolo left a comment

Choose a reason for hiding this comment

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

I think the current benchmark result does not reflect improvements in this pull request.
Would it be possible to add a benchmark that demonstrates the performance difference before and after this pull request?

@cecton
Copy link
Member Author

cecton commented Oct 2, 2023

Yes 100% agreed..... just need to figure out how xD I think a classic benchmark with criterion on different kind of VNode will work best

Copy link
Member

@ranile ranile left a comment

Choose a reason for hiding this comment

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

Nothing jumps out by skimming through the code. I agree with futursolo that it needs to benchmarked though

@cecton
Copy link
Member Author

cecton commented Oct 5, 2023

There is a new & shiny library 🙌 https://hachyderm.io/@nikolai/111179659061831881

@ranile
Copy link
Member

ranile commented Oct 7, 2023

There is a new & shiny library 🙌 https://hachyderm.io/@nikolai/111179659061831881

It doesn't run on WASM: nvzqz/divan#3

@cecton
Copy link
Member Author

cecton commented Oct 18, 2023

I'm struggling with this workflow xD @futursolo maybe you can help me? I think the commit befcaa2 would have work but the post thing doesn't start. I believe it is because the workflow does not exist yet on the main branch. So I changed it to use 2 steps instead of 2 workflows (e0711b1) and now I have a 403.

Note: This event will only trigger a workflow run if the workflow file is on the default branch.

(From the doc)

@futursolo
Copy link
Member

I believe it is because the workflow does not exist yet on the main branch. So I changed it to use 2 steps instead of 2 workflows (e0711b1) and now I have a 403.

I think the original approach should work.

GitHub Actions no longer allows pull_request trigger to access protect resources, including posting comments.
You need a separate workflow with a different trigger to post comments.

The only way to figure out if it works is to merge the benchmark and create an additional pull request to test.

@@ -16,25 +17,27 @@ use crate::AttrValue;
#[must_use = "html does not do anything unless returned to Yew for rendering."]
pub enum VNode {
Copy link
Member

Choose a reason for hiding this comment

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

May I ask why option 1 is selected by this pull request?

I feel other options would produce better public APIs.

Copy link
Member Author

Choose a reason for hiding this comment

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

I remember I couldn't do option 2. I got lost in the change and didn't manage to make it work.

Option 3 is actually used here. It's a mix of option 1 and option 3. In some cases, cloning a single object was cheaper so I added Rc in places it wasn't strictly necessary. (related to #3431 (comment))

Now if I recall I think there wasn't a strong interest of going for one or the other option so I did go wherever it worked.

Copy link
Member Author

@cecton cecton Oct 27, 2023

Choose a reason for hiding this comment

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

I think in the end we need both option 1 and 3. Because option 1 is better for the user as they will pass html nodes (Html/VNode) through props so this need to be fast. But option 3 is important for the internals of Yew. Huh but it's really just theory.

Copy link
Member

@ranile ranile Oct 27, 2023

Choose a reason for hiding this comment

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

Users may also want to pass VChild/VList directly for a better API to components (but those are already cheap to clone, so option 3 is already somewhat implemented)

@cecton cecton marked this pull request as ready for review October 24, 2023 08:54
github-actions[bot]
github-actions bot previously approved these changes Oct 24, 2023
@cecton
Copy link
Member Author

cecton commented Oct 24, 2023

The only way to figure out if it works is to merge the benchmark and create an additional pull request to test.

Ok I have put back the 2 workflows files and I think it's ready to merge.

I think this PR is very important and we should be absolutely sure that the implementation is right as we want it to be. So feel free to take your time to review again @hamza1311 @futursolo maybe others will have opinion on this.

From my point of view I don't see much differences between the different options but I do think having VNode (or Html) cheap-to-clone is a MUST have.

@alexkazik
Copy link

Out of curiosity: if VList is already cheap to clone (ImplicitClone) why is VNode::VList with Rc?

@cecton
Copy link
Member Author

cecton commented Oct 26, 2023

Out of curiosity: if VList is already cheap to clone (ImplicitClone) why is VNode::VList with Rc?

I think it was cheaper to clone 1 Rc instead of multiple ones? At least that's my theory. But let's see what the benchmark says...

With Rc wrapping VList:

vnode           fastest       │ slowest       │ median        │ mean          │ samples │ iters
╰─ vnode_clone  1.787 ns      │ 3.351 ns      │ 1.797 ns      │ 1.814 ns      │ 100     │ 1000000000

Without Rc wrapping VList:

vnode           fastest       │ slowest       │ median        │ mean          │ samples │ iters
╰─ vnode_clone  3.338 ns      │ 5.379 ns      │ 3.367 ns      │ 3.393 ns      │ 100     │ 1000000000

@ranile
Copy link
Member

ranile commented Oct 26, 2023

@cecton the best way to ensure the workflow works is rip it out of this PR and make another one with the benchmarks that's merged before this one. Then you can rebase this one and get the benchmark results

@cecton
Copy link
Member Author

cecton commented Oct 26, 2023

@cecton the best way to ensure the workflow works is rip it out of this PR and make another one with the benchmarks that's merged before this one. Then you can rebase this one and get the benchmark results

I don't know why I didn't think of that earlier xD

@cecton cecton mentioned this pull request Oct 26, 2023
2 tasks
@ranile
Copy link
Member

ranile commented Oct 27, 2023

@cecton I merged #3487, can you rebase this?

github-actions[bot]
github-actions bot previously approved these changes Oct 27, 2023
github-actions[bot]
github-actions bot previously approved these changes Oct 27, 2023
@github-actions
Copy link

github-actions bot commented Oct 27, 2023

Benchmark - core

Yew Master

vnode           fastest       │ slowest       │ median        │ mean          │ samples │ iters
╰─ vnode_clone  78.23 ns      │ 86.75 ns      │ 80.8 ns       │ 80.9 ns       │ 100     │ 1000000000

Pull Request" >> comment.txt

vnode           fastest       │ slowest       │ median        │ mean          │ samples │ iters
╰─ vnode_clone  5.215 ns      │ 6.788 ns      │ 5.434 ns      │ 5.548 ns      │ 100     │ 1000000000

@cecton
Copy link
Member Author

cecton commented Oct 27, 2023

@ everyone dont hesitate to push commits on the PR to test things out!

Copy link
Member

@ranile ranile left a comment

Choose a reason for hiding this comment

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

I'm fine with merging it. There is more indirection in reading the data, not sure how that affects things. Cheap cloning is very important for Html as it's everywhere and cloned most of the time it's used

The benchmarks show a big improvement and no one has raised any issues with the implementation so I'm going to go ahead and merge this. If anything comes up, it can always be addressed later.

@ranile ranile merged commit 7f45af3 into yewstack:master Oct 27, 2023
21 checks passed
@cecton cecton deleted the html-cheap-to-clone branch October 31, 2023 12:32
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 breaking change
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants