slawlor / ractor

Rust actor framework
MIT License
1.38k stars 69 forks source link

Support async_std as a runtime #173

Closed slawlor closed 11 months ago

slawlor commented 1 year ago

This PR adds support for the async-std runtime as an alternative to the tokio runtime. It can be enabled with the async-std feature.

Note: ractor uses some core primitives or functionality of structs from tokio which required some wrapping to support in async-std. Specifically:

  1. tokio's JoinHandle has functionality to determine if a JoinHandle is finished as well as to abort it without consuming the handle. These required some wrapping in our async_std_primatives module to support similar functionality without great rewrites of ractor. Basic functionality test coverage is added for our custom JoinHandle implementation.
  2. tokio has a JoinSet which has some minor syntactical changes from the standard FuturesUnordered from the futures crate which we can leverage in its stead. Again a small wrapper was added.
  3. tokio has an Interval which is used to fix #57, this doesn't exist in async-std aside from a basic sleep implementation, so we had to add a custom version of it.
codecov[bot] commented 1 year ago

Codecov Report

Attention: 4 lines in your changes are missing coverage. Please review.

Comparison is base (1ae8d86) 79.20% compared to head (20aae31) 79.23%.

Additional details and impacted files ```diff @@ Coverage Diff @@ ## main #173 +/- ## ========================================== + Coverage 79.20% 79.23% +0.02% ========================================== Files 49 50 +1 Lines 9123 9153 +30 ========================================== + Hits 7226 7252 +26 - Misses 1897 1901 +4 ``` | [Files](https://app.codecov.io/gh/slawlor/ractor/pull/173?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Sean+Lawlor) | Coverage Δ | | |---|---|---| | [ractor/src/actor/actor\_cell.rs](https://app.codecov.io/gh/slawlor/ractor/pull/173?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Sean+Lawlor#diff-cmFjdG9yL3NyYy9hY3Rvci9hY3Rvcl9jZWxsLnJz) | `95.33% <100.00%> (+0.33%)` | :arrow_up: | | [ractor/src/actor/tests/mod.rs](https://app.codecov.io/gh/slawlor/ractor/pull/173?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Sean+Lawlor#diff-cmFjdG9yL3NyYy9hY3Rvci90ZXN0cy9tb2QucnM=) | `91.65% <100.00%> (ø)` | | | [ractor/src/concurrency/tokio\_primatives.rs](https://app.codecov.io/gh/slawlor/ractor/pull/173?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Sean+Lawlor#diff-cmFjdG9yL3NyYy9jb25jdXJyZW5jeS90b2tpb19wcmltYXRpdmVzLnJz) | `100.00% <100.00%> (ø)` | | | [ractor/src/port/output/mod.rs](https://app.codecov.io/gh/slawlor/ractor/pull/173?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Sean+Lawlor#diff-cmFjdG9yL3NyYy9wb3J0L291dHB1dC9tb2QucnM=) | `96.92% <100.00%> (ø)` | | | [ractor/src/port/output/tests.rs](https://app.codecov.io/gh/slawlor/ractor/pull/173?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Sean+Lawlor#diff-cmFjdG9yL3NyYy9wb3J0L291dHB1dC90ZXN0cy5ycw==) | `94.73% <100.00%> (ø)` | | | [ractor/src/rpc/mod.rs](https://app.codecov.io/gh/slawlor/ractor/pull/173?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Sean+Lawlor#diff-cmFjdG9yL3NyYy9ycGMvbW9kLnJz) | `89.51% <100.00%> (ø)` | | | [ractor/src/time/mod.rs](https://app.codecov.io/gh/slawlor/ractor/pull/173?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Sean+Lawlor#diff-cmFjdG9yL3NyYy90aW1lL21vZC5ycw==) | `100.00% <100.00%> (ø)` | | | [ractor/src/concurrency/mod.rs](https://app.codecov.io/gh/slawlor/ractor/pull/173?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Sean+Lawlor#diff-cmFjdG9yL3NyYy9jb25jdXJyZW5jeS9tb2QucnM=) | `92.30% <92.30%> (ø)` | | | [ractor/src/factory/tests/mod.rs](https://app.codecov.io/gh/slawlor/ractor/pull/173?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Sean+Lawlor#diff-cmFjdG9yL3NyYy9mYWN0b3J5L3Rlc3RzL21vZC5ycw==) | `90.58% <88.88%> (-0.08%)` | :arrow_down: | | [ractor/src/pg/tests.rs](https://app.codecov.io/gh/slawlor/ractor/pull/173?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Sean+Lawlor#diff-cmFjdG9yL3NyYy9wZy90ZXN0cy5ycw==) | `93.10% <85.71%> (-0.29%)` | :arrow_down: | | ... and [1 more](https://app.codecov.io/gh/slawlor/ractor/pull/173?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Sean+Lawlor) | | ... and [2 files with indirect coverage changes](https://app.codecov.io/gh/slawlor/ractor/pull/173/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Sean+Lawlor)

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

slawlor commented 12 months ago

A note on performance

Running our benchmark suite we can measure somewhat the performance delta between tokio and async-std, however these only measure very basic operations and not all functionality in the crate.

Starting with tokio, we have

$ cargo bench -p ractor
...
Creation of 100 actors  time:   [402.38 µs 414.38 µs 431.41 µs]
Found 8 outliers among 100 measurements (8.00%)
  2 (2.00%) low mild
  3 (3.00%) high mild
  3 (3.00%) high severe

Waiting on 100 actors to process first message
                        time:   [953.14 µs 1.0024 ms 1.0515 ms]
Found 12 outliers among 100 measurements (12.00%)
  8 (8.00%) high mild
  4 (4.00%) high severe

Waiting on 1000 actors to process first message
                        time:   [9.8127 ms 9.9778 ms 10.148 ms]
Found 2 outliers among 100 measurements (2.00%)
  2 (2.00%) high mild

Waiting on 100000 messages to be processed
                        time:   [23.755 ms 23.875 ms 24.001 ms]
Found 1 outliers among 100 measurements (1.00%)
  1 (1.00%) high mild

Then running again with the async-std runtime

$ cargo bench -p ractor --features async-std

Creation of 100 actors  time:   [470.98 µs 482.73 µs 500.55 µs]
                        change: [+15.865% +18.363% +21.029%] (p = 0.00 < 0.05)
                        Performance has regressed.
Found 10 outliers among 100 measurements (10.00%)
  1 (1.00%) low severe
  1 (1.00%) low mild
  5 (5.00%) high mild
  3 (3.00%) high severe

Benchmarking Creation of 10000 actors: Warming up for 3.0000 s
Warning: Unable to complete 100 samples in 5.0s. You may wish to increase target time to 5.1s, or reduce sample count to 90.
Creation of 10000 actors
                        time:   [54.189 ms 55.454 ms 56.750 ms]
                        change: [+25.379% +29.767% +34.366%] (p = 0.00 < 0.05)
                        Performance has regressed.

Benchmarking Waiting on 100 actors to process first message: Warming up for 3.0000 s
Warning: Unable to complete 100 samples in 5.0s. You may wish to increase target time to 2892.0s, or reduce sample count to 10.
Waiting on 100 actors to process first message
                        time:   [700.84 µs 750.61 µs 799.74 µs]
                        change: [-29.340% -21.688% -14.527%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 8 outliers among 100 measurements (8.00%)
  5 (5.00%) low mild
  3 (3.00%) high mild

Waiting on 1000 actors to process first message
                        time:   [8.9662 ms 9.1759 ms 9.4057 ms]
                        change: [-10.577% -8.0368% -5.1212%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 6 outliers among 100 measurements (6.00%)
  3 (3.00%) high mild
  3 (3.00%) high severe

This shows that actor creation is more expensive in async-std but trivial message processing schedules faster. We likely need more complex performance tests to compare the runtime functionalities better, but this is a start showing reasonable performance in either runtime.