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

Refactor the execution to avoid setTimeout #2999

Merged
merged 4 commits into from
Nov 14, 2022
Merged

Conversation

tomaka
Copy link
Contributor

@tomaka tomaka commented Nov 11, 2022

Close #2996

This PR does many things:

  • Remove the crate::util::yield_twice function in favor of a platform-specific function TPlat::yield_after_cpu_intensive. This way, the implementation of the yielding, which is a bit hacky due to the requirements of the Wasm node, is specific to the Wasm node.

  • Refactor the nextJsonRpcResponse function and the jsonRpcResponsesNonEmptyCallback callback. Right now, when we wait for a JSON-RPC response to come, we wait for smoldot to notify that it has a response available. But because this notification is done through a callback, we can't immediately query the content of the response, so instead we use setTimeout(..., 0) to register a task that queries the content of the response and then notify the Promise that was waiting. Now we instead immediately notify a Promise, and this Promise then queries the content of the response as an aftermath.

  • In the JS code, add a registerShouldPeriodicallyYield function whose implementation is "platform-specific" (browsers, NodeJS, Deno). This function controls a new setting called "should periodically yield". In NodeJS and Deno, this is always false. In the browser, this is false if and only if the page is in the background and true if it is in the foreground. Passing false reduces the usage of setTimeout, while passing true promotes the usage of setTimeout to avoid blocking the browser.

  • In the JS <-> Rust bindings, add a periodically_yield parameter to init and add a new set_periodically_yield function. See above point.

  • Refactor the way the execution is done. Currently we spawn at initialization a task (using setTimeout(..., 0)) that runs everything. When something needs to be executed, this task wakes up by calling setTimeout(..., 0) again. After this PR, there is no "background task" anymore. Instead, the Future that drives everything is now put in CLIENT variable, and every single binding function calls a new advance_execution function before returning. advance_execution polls that Future and, depending on the periodically_yield setting, either executes everything until there is nothing more to do, or executes until the first yield.

All these changes eliminate the usage of setTimeout to the strict minimum, which is when we actually need a timer.

Copy link
Contributor

@mergify mergify bot left a comment

Choose a reason for hiding this comment

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

Automatically approving tomaka's pull requests. This auto-approval will be removed once more maintainers are active.

@github-actions
Copy link
Contributor

github-actions bot commented Nov 11, 2022

twiggy diff report

Difference in .wasm size before and after this pull request.


 Delta Bytes │ Item
─────────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
       -4024 ┊ <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll::h9dada38497f26188
       +4008 ┊ <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll::h03a716e5ebe0e388
       -1563 ┊ <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll::h38f23d1b0bef50b0
       +1511 ┊ <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll::hcb29fc77c900642a
       -1438 ┊ <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll::h9a1c842d5804e797
       +1422 ┊ <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll::he66754c63cc55c41
        -850 ┊ <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll::h36b6de422e453f9e
        +799 ┊ <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll::h22535c4cce2a5d84
        +460 ┊ <smoldot_light_wasm::platform::StreamWrapper as core::ops::drop::Drop>::drop::h22361dafd929fb6c
        -460 ┊ <smoldot_light_wasm::platform::StreamWrapper as core::ops::drop::Drop>::drop::h47f8e42efc1ec7d1
        -413 ┊ core::ptr::drop_in_place<core::future::from_generator::GenFuture<smoldot_light::sync_service::standalone::start_standalone_chain<smoldot_light_wasm::platform::Platform>::{{closure}}>>::hc4e7126920348830
        +413 ┊ core::ptr::drop_in_place<core::future::from_generator::GenFuture<smoldot_light::sync_service::standalone::start_standalone_chain<smoldot_light_wasm::platform::Platform>::{{closure}}>>::hf5fc2f1cdb0faa63
        +394 ┊ smoldot_light_wasm::advance_execution::h2bdd92c2f57f0ca6
        -355 ┊ core::ops::function::FnOnce::call_once{{vtable.shim}}::h2f37880895ab865b
        -289 ┊ <smoldot_light_wasm::cpu_rate_limiter::CpuRateLimiter<T> as core::future::future::Future>::poll::h08b3f962d41e5210
        +286 ┊ <smoldot_light_wasm::cpu_rate_limiter::CpuRateLimiter<T> as core::future::future::Future>::poll::h5d8fdc5f2213fe44
        -281 ┊ <smoldot_light_wasm::platform::ConnectionWrapper as core::ops::drop::Drop>::drop::hbae057c8a5679c4b
        +281 ┊ <smoldot_light_wasm::platform::ConnectionWrapper as core::ops::drop::Drop>::drop::he844ad5ccc546bc7
        -274 ┊ <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll::h54fd24c9737005d8
        +272 ┊ <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll::h3c89f40c3c4f8a2d
         +61 ┊ ... and 116 more.
        -558 ┊ Σ [136 Total Rows]

@tomaka
Copy link
Contributor Author

tomaka commented Nov 11, 2022

Testing this PR is a bit complicated.
However, before this PR, when I leave smoldot running in a background tab, I get disconnects and timeouts.
After this PR, this no longer happens, so I would say that it works.

EDIT: actually, still getting timeouts afterwards, so inconclusive.

EDIT 2: it definitely works better after the PR

@tomaka tomaka added the automerge Automatically merge pull request as soon as possible label Nov 14, 2022
@mergify mergify bot merged commit 5b30f5e into paritytech:main Nov 14, 2022
@tomaka tomaka deleted the fix-2996 branch November 14, 2022 08:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
automerge Automatically merge pull request as soon as possible
Projects
None yet
Development

Successfully merging this pull request may close these issues.

setTimeout has a minimum delay of 1 second (or 15mn on mobile) in inactive tabs
2 participants