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

Pinned Channels #2811

Merged
merged 20 commits into from Aug 16, 2022
Merged

Pinned Channels #2811

merged 20 commits into from Aug 16, 2022

Conversation

futursolo
Copy link
Member

@futursolo futursolo commented Aug 5, 2022

Description

This pull request introduces a channel implementation that is !Send.

mpsc channel, 1,000,000 channels, send 10 items each, same task:

Futures Channel: 294ms
Tokio Channel:   340ms
Yew Channel:     120ms

mpsc channel, 1,000,000 channels, send 10 items each, different task:

Futures Channel: 360ms
Tokio Channel:   389ms
Yew Channel:     192ms

oneshot channel, send 10,000,000 items, same task:

Futures Oneshot: 380ms
Tokio Oneshot:   253ms
Yew Oneshot:     133ms

oneshot channel, send 10,000,000 items, different task:
(note: cost of task spawning is substantially more expensive than sending through oneshot channel itself.)

Futures Oneshot: 966ms
Tokio Oneshot:   1065ms
Yew Oneshot:     893ms

Checklist

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

@futursolo futursolo added the A-yew Area: The main yew crate label Aug 5, 2022
github-actions[bot]
github-actions bot previously approved these changes Aug 5, 2022
@futursolo futursolo mentioned this pull request Aug 5, 2022
2 tasks
@github-actions
Copy link

github-actions bot commented Aug 5, 2022

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

https://yew-rs-api--pr2811-pinned-channels-a6yq3teq.web.app

(expires Mon, 22 Aug 2022 18:04:28 GMT)

🔥 via Firebase Hosting GitHub Action 🌎

@github-actions
Copy link

github-actions bot commented Aug 5, 2022

Benchmark - SSR

Yew Master

Benchmark Round Min (ms) Max (ms) Mean (ms) Standard Deviation
Baseline 10 434.703 476.157 446.788 13.359
Hello World 10 1242.081 1394.976 1301.532 59.349
Function Router 10 3262.743 3508.886 3345.685 90.151
Concurrent Task 10 1013.074 1016.943 1014.402 1.505

Pull Request

Benchmark Round Min (ms) Max (ms) Mean (ms) Standard Deviation
Baseline 10 435.967 481.270 452.306 16.520
Hello World 10 1202.872 1388.751 1253.956 57.993
Function Router 10 3144.109 3425.877 3266.969 94.842
Concurrent Task 10 1012.602 1016.692 1014.323 1.185

@github-actions
Copy link

github-actions bot commented Aug 5, 2022

Size Comparison

examples master (KB) pull request (KB) diff (KB) diff (%)
boids 169.301 169.310 +0.009 +0.005%
contexts 107.364 107.358 -0.006 -0.005%
counter 84.875 84.875 0 0.000%
counter_functional 85.499 85.500 +0.001 +0.001%
dyn_create_destroy_apps 87.800 87.802 +0.002 +0.002%
file_upload 101.396 101.396 0 0.000%
function_memory_game 162.893 162.881 -0.012 -0.007%
function_router 345.784 345.782 -0.002 -0.001%
function_todomvc 157.918 157.918 0 0.000%
futures 221.961 221.960 -0.001 -0.000%
game_of_life 105.171 105.171 0 0.000%
immutable 180.710 180.712 +0.002 +0.001%
inner_html 81.977 81.976 -0.001 -0.001%
js_callback 110.684 110.687 +0.003 +0.003%
keyed_list 193.473 193.474 +0.001 +0.001%
mount_point 84.660 84.658 -0.002 -0.002%
nested_list 112.274 112.273 -0.001 -0.001%
node_refs 91.818 91.816 -0.002 -0.002%
password_strength 1548.209 1548.209 0 0.000%
portals 95.398 95.398 0 0.000%
router 315.245 315.250 +0.005 +0.002%
simple_ssr 151.344 151.344 0 0.000%
ssr_router 391.298 391.300 +0.002 +0.000%
suspense 108.418 108.417 -0.001 -0.001%
timer 87.644 87.646 +0.002 +0.002%
todomvc 139.266 139.266 0 0.000%
two_apps 85.521 85.521 0 0.000%
web_worker_fib 150.503 150.510 +0.007 +0.005%
webgl 85.656 85.654 -0.002 -0.002%

✅ None of the examples has changed their size significantly.

github-actions[bot]
github-actions bot previously approved these changes Aug 5, 2022
# Conflicts:
#	packages/yew/src/virtual_dom/vlist.rs
github-actions[bot]
github-actions bot previously approved these changes Aug 7, 2022
github-actions[bot]
github-actions bot previously approved these changes Aug 8, 2022
@futursolo futursolo marked this pull request as draft August 11, 2022 17:12
@futursolo futursolo mentioned this pull request Aug 12, 2022
2 tasks
@futursolo
Copy link
Member Author

futursolo commented Aug 13, 2022

With #2824, SSR no longer uses mpsc channels. I have updated this pull request to remove the BufWriter implementation.
It's still beneficial to land this pull request as the pinned oneshot channels can still be used in SSR and mpsc channels are widely used in #2773.

@futursolo futursolo marked this pull request as ready for review August 13, 2022 07:44
github-actions[bot]
github-actions bot previously approved these changes Aug 13, 2022
Copy link
Member

@hamza1311 hamza1311 left a comment

Choose a reason for hiding this comment

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

Sorry it took me a while to get to this. All the comments are about the same thing: missing safety comment for unsafe. It's very important to have comments explaining why de-referencing the pointers are important here. Those who aren't familiar with the code can have a hard time understanding what's happening, or worse contribute/merge a change that is unsound. That could be someone new, me or even (future) you.

We should have #[deny(clippy::missing_safety_doc)] so unsafe functions are checked for this too. It would be great to run miri in CI. These 2 can be done in separate PRs though.

packages/yew/src/platform/pinned/mpsc.rs Outdated Show resolved Hide resolved
packages/yew/src/platform/pinned/mpsc.rs Outdated Show resolved Hide resolved
packages/yew/src/platform/pinned/mpsc.rs Outdated Show resolved Hide resolved
packages/yew/src/platform/pinned/mpsc.rs Outdated Show resolved Hide resolved
packages/yew/src/platform/pinned/mpsc.rs Outdated Show resolved Hide resolved
packages/yew/src/platform/pinned/mpsc.rs Outdated Show resolved Hide resolved
packages/yew/src/platform/pinned/oneshot.rs Outdated Show resolved Hide resolved
packages/yew/src/platform/pinned/oneshot.rs Outdated Show resolved Hide resolved
packages/yew/src/platform/pinned/oneshot.rs Outdated Show resolved Hide resolved
packages/yew/src/platform/pinned/oneshot.rs Outdated Show resolved Hide resolved
github-actions[bot]
github-actions bot previously approved these changes Aug 14, 2022
Copy link
Member

@WorldSEnder WorldSEnder left a comment

Choose a reason for hiding this comment

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

I believe the unsafe blocks are now okay, though a few unsafes can be dropped and the phrasing in the SAFETY comments could be improved to:

SAFETY: the ref is not aliased inside this function and dropped before returning. It will be the only ref to the contents.

Being pedantic, a very odd waker implementation could trigger re-entrant code and an aliasing mutable borrow, I believe. The borrow is still active after calling out to arbitrary code a8ee1c0#diff-31d23a5f32d50a4ab7bdff4a7fdc162fc1eaf6597c349f407c4076d83b35377cR54 I'm not really concerned about that, though. I believe it's fine to leave as is.

packages/yew/src/platform/pinned/mpsc.rs Show resolved Hide resolved
packages/yew/src/platform/pinned/mpsc.rs Show resolved Hide resolved
packages/yew/src/platform/pinned/oneshot.rs Show resolved Hide resolved
@WorldSEnder WorldSEnder dismissed their stale review August 14, 2022 22:39

unsafe now okay

github-actions[bot]
github-actions bot previously approved these changes Aug 14, 2022
github-actions[bot]
github-actions bot previously approved these changes Aug 14, 2022
github-actions[bot]
github-actions bot previously approved these changes Aug 14, 2022
WorldSEnder
WorldSEnder previously approved these changes Aug 15, 2022
Copy link
Member

@hamza1311 hamza1311 left a comment

Choose a reason for hiding this comment

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

Would it be better off if this were a separate library so non-yew users can also use it?

Comment on lines +102 to +111
let inner = unsafe { &mut *self.inner.get() };

match (inner.items.pop_front(), inner.closed) {
(Some(m), _) => Poll::Ready(Some(m)),
(None, false) => {
inner.rx_waker = Some(cx.waker().clone());
Poll::Pending
}
(None, true) => Poll::Ready(None),
}
Copy link
Member

Choose a reason for hiding this comment

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

This can call try_next and map the Result<Option<_>, _> instead duplicating it's implementation?

Copy link
Member Author

Choose a reason for hiding this comment

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

We cannot avoid acquiring the mutable reference to inner as we have to store the waker.

(it’s an equal number of lines to map Result<Option<_>, _> to Poll::* and current implementation.)

Copy link
Member

Choose a reason for hiding this comment

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

I was hoping to avoid unsafely obtaining the mutable reference. The lines of code doesn't really matter here

Comment on lines +140 to +141
let inner = unsafe { &mut *self.inner.get() };
inner.close();
Copy link
Member

Choose a reason for hiding this comment

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

What about freeing the inner? Does UnsafeCell takes care of it? I couldn't find anything about drop behavior in UnsafeCell documentation, nor does it implement Drop

Copy link
Member Author

Choose a reason for hiding this comment

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

UnsafeCell is a plain struct with an inner of type T. The drop behaviour is handled normally as any other type.

packages/yew/src/platform/pinned/mpsc.rs Show resolved Hide resolved
Comment on lines +298 to +299
#[cfg(not(target_arch = "wasm32"))]
#[cfg(feature = "tokio")]
Copy link
Member

Choose a reason for hiding this comment

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

Can we run these tests on both targets?

#[derive(Error, Debug)]
#[error("queue is empty")]
pub struct TryRecvError {
_marker: PhantomData<()>,
Copy link
Member

Choose a reason for hiding this comment

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

Why have these markers?

Copy link
Member Author

Choose a reason for hiding this comment

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

This is to mark that there is a hidden information in this struct.

Some other struct have this as we need to expand and add error reason in the future. This is here to keep consistency.

@futursolo
Copy link
Member Author

Would it be better off if this were a separate library so non-yew users can also use it?

I feel yew::platform should be in its own crate. However, this can be done in a future pull request.

Co-authored-by: Muhammad Hamza <muhammadhamza1311@gmail.com>
Copy link
Member

@hamza1311 hamza1311 left a comment

Choose a reason for hiding this comment

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

Looks good.

I agree that yew::platform should be it's own crate. The channels in this PR can be another crate that yew-platform depends upon

@futursolo futursolo merged commit 5079885 into yewstack:master Aug 16, 2022
@futursolo futursolo deleted the pinned-channels branch December 15, 2022 10:14
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
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

None yet

3 participants