Skip to content

feat: add scheduler::flush() to replace sleep(Duration::ZERO) in tests#4044

Merged
Madoshakalaka merged 3 commits intomasterfrom
test-runner-lite
Mar 7, 2026
Merged

feat: add scheduler::flush() to replace sleep(Duration::ZERO) in tests#4044
Madoshakalaka merged 3 commits intomasterfrom
test-runner-lite

Conversation

@Madoshakalaka
Copy link
Member

@Madoshakalaka Madoshakalaka commented Mar 5, 2026

Description

a small part of #2679

Checklist

  • I have reviewed my own code

@github-actions
Copy link

github-actions bot commented Mar 5, 2026

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

https://yew-rs-api--pr4044-test-runner-lite-7n47edyn.web.app

(expires Thu, 12 Mar 2026 16:13:33 GMT)

🔥 via Firebase Hosting GitHub Action 🌎

@github-actions
Copy link

github-actions bot commented Mar 5, 2026

Benchmark - core

Yew Master

vnode           fastest       │ slowest       │ median        │ mean          │ samples │ iters
╰─ vnode_clone  2.403 ns      │ 3.937 ns      │ 3.648 ns      │ 3.161 ns      │ 100     │ 1000000000

Pull Request

vnode           fastest       │ slowest       │ median        │ mean          │ samples │ iters
╰─ vnode_clone  2.361 ns      │ 2.924 ns      │ 2.365 ns      │ 2.377 ns      │ 100     │ 1000000000

@github-actions
Copy link

github-actions bot commented Mar 5, 2026

Size Comparison

Details
examples master (KB) pull request (KB) diff (KB) diff (%)
async_clock 100.196 100.196 0 0.000%
boids 168.082 168.082 0 0.000%
communication_child_to_parent 93.469 93.469 0 0.000%
communication_grandchild_with_grandparent 105.251 105.251 0 0.000%
communication_grandparent_to_grandchild 101.604 101.604 0 0.000%
communication_parent_to_child 90.897 90.897 0 0.000%
contexts 105.150 105.150 0 0.000%
counter 86.281 86.281 0 0.000%
counter_functional 88.275 88.275 0 0.000%
dyn_create_destroy_apps 90.322 90.322 0 0.000%
file_upload 99.345 99.345 0 0.000%
function_delayed_input 94.377 94.377 0 0.000%
function_memory_game 172.946 172.946 0 0.000%
function_router 405.670 405.672 +0.002 +0.000%
function_todomvc 164.163 164.163 0 0.000%
futures 235.158 235.158 0 0.000%
game_of_life 104.717 104.717 0 0.000%
immutable 255.846 255.846 0 0.000%
inner_html 80.802 80.802 0 0.000%
js_callback 109.377 109.377 0 0.000%
keyed_list 179.729 179.729 0 0.000%
mount_point 84.146 84.146 0 0.000%
nested_list 113.057 113.057 0 0.000%
node_refs 91.526 91.526 0 0.000%
password_strength 1728.824 1728.824 0 0.000%
portals 93.036 93.036 0 0.000%
router 376.233 376.248 +0.015 +0.004%
suspense 113.454 113.454 0 0.000%
timer 88.633 88.633 0 0.000%
timer_functional 98.878 98.878 0 0.000%
todomvc 142.087 142.087 0 0.000%
two_apps 86.146 86.146 0 0.000%
web_worker_fib 136.237 136.237 0 0.000%
web_worker_prime 187.471 187.471 0 0.000%
webgl 83.225 83.225 0 0.000%

✅ None of the examples has changed their size significantly.

@github-actions
Copy link

github-actions bot commented Mar 5, 2026

Benchmark - SSR

Yew Master

Details
Benchmark Round Min (ms) Max (ms) Mean (ms) Standard Deviation
Baseline 10 310.666 312.412 311.085 0.497
Hello World 10 478.851 490.591 483.245 4.042
Function Router 10 31712.211 32381.623 32123.295 240.866
Concurrent Task 10 1006.519 1008.045 1007.393 0.433
Many Providers 10 1103.856 1138.215 1121.344 11.043

Pull Request

Details
Benchmark Round Min (ms) Max (ms) Mean (ms) Standard Deviation
Baseline 10 311.300 314.370 313.526 1.079
Hello World 10 477.776 506.681 485.054 7.983
Function Router 10 31298.203 32047.661 31831.082 219.489
Concurrent Task 10 1005.894 1008.309 1007.568 0.708
Many Providers 10 1108.302 1144.312 1120.040 10.235

@Madoshakalaka Madoshakalaka force-pushed the test-runner-lite branch 4 times, most recently from a210fdb to 22fc46c Compare March 5, 2026 13:00
Add a public `scheduler::flush()` async function that properly waits for
all pending scheduler work to complete. This replaces the 61 uses of
`sleep(Duration::ZERO).await` across 12 test files with a semantically
clear, centralized call that can be improved in the future.

Consecutive zero-duration sleeps (used in hydration tests as a
conservative measure) are collapsed to a single flush(), since one
macrotask yield is sufficient to drain all cascading microtask work.
sleep(Duration::ZERO).await;
sleep(Duration::ZERO).await;
sleep(Duration::ZERO).await;
scheduler::flush().await;
Copy link
Member Author

Choose a reason for hiding this comment

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

real proof of flush correctness

@Madoshakalaka Madoshakalaka marked this pull request as ready for review March 5, 2026 13:49
github-actions[bot]
github-actions bot previously approved these changes Mar 5, 2026
@Madoshakalaka
Copy link
Member Author

properly gated too (no binary size diff)
I think it's a win

It will help with #4033

@WorldSEnder

@Madoshakalaka Madoshakalaka marked this pull request as draft March 5, 2026 13:54
@Madoshakalaka Madoshakalaka marked this pull request as ready for review March 5, 2026 14:10
github-actions[bot]
github-actions bot previously approved these changes Mar 5, 2026
Comment on lines +322 to +364
/// Future returned by [`flush()`] that resolves when the scheduler finishes all pending work.
///
/// On each poll, this future eagerly drains any currently-queued scheduler work via
/// `start_now()`. It then checks whether the scheduler has been re-scheduled (via
/// `IS_SCHEDULED`), which indicates that spawned microtasks (e.g., from Suspense futures
/// resolving) will trigger more work. If so, it re-registers its waker and yields, allowing
/// those microtasks to execute before the next poll. This loop continues until the scheduler
/// is truly idle.
#[cfg(all(
any(test, feature = "test"),
target_arch = "wasm32",
not(target_os = "wasi"),
not(feature = "not_browser_env")
))]
#[derive(Debug)]
pub struct Flush {
_priv: (),
}

#[cfg(all(
any(test, feature = "test"),
target_arch = "wasm32",
not(target_os = "wasi"),
not(feature = "not_browser_env")
))]
impl std::future::Future for Flush {
type Output = ();

fn poll(
self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<()> {
start_now();

if arch::is_scheduled() {
flush_wakers::register(cx.waker().clone());
std::task::Poll::Pending
} else {
std::task::Poll::Ready(())
}
}
}

Copy link
Member

Choose a reason for hiding this comment

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

This future could be simply implemented with std::future::poll_fn.

Copy link
Member Author

Choose a reason for hiding this comment

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

Good call, done.

target_arch = "wasm32",
not(target_os = "wasi"),
not(feature = "not_browser_env")
))]
Copy link
Member

Choose a reason for hiding this comment

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

Could these three lines be moved into the function for a uniform signature (and documentation) across targets.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done, both targets now use pub async fn flush()

github-actions[bot]
github-actions bot previously approved these changes Mar 5, 2026
@Madoshakalaka Madoshakalaka merged commit 8a222d7 into master Mar 7, 2026
35 checks passed
@Madoshakalaka Madoshakalaka deleted the test-runner-lite branch March 7, 2026 12:18
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.

2 participants