Commit Graph
53 Commits
Author SHA1 Message Date
Carl Lerche 4165601b1b rt: initial implementation of new threaded runtime (#5823)
This patch includes an initial implementation of a new multi-threaded
runtime. The new runtime aims to increase the scheduler throughput by
speeding up how it dispatches work to peer worker threads. This
implementation improves most benchmarks by about ~10% when the number of
threads is below 16. As threads increase, mutex contention deteriorates
performance.

Because the new scheduler is not yet ready to replace the old one, the
patch introduces it as an unstable runtime flavor with a warning that it
isn't production ready. Work to improve the scalability of the runtime
will most likely require more intrusive changes across Tokio, so I am
opting to merge with master to avoid larger conflicts.
2023-07-21 11:56:34 -07:00
Carl Lerche 93bde0870f rt: use task::Inject with current_thread scheduler (#5702)
Previously, the current_thread scheduler used its own injection queue
instead of sharing the same one as the multi-threaded scheduler. This
patch updates the current_thread scheduler to use the same injection
queue as the multi-threaded one (`task::Inject`).

`task::Inject` includes an optimization where it does not need to
acquire the mutex if the queue is empty.
2023-05-21 00:08:00 +00:00
Alice Ryhl b9868b23aa rt: fix spurious yield_defers_until_park test (#5634) 2023-04-20 18:00:33 +02:00
Carl Lerche 22cff80048 chore: update CI's clippy version to 1.65 (#5276) 2022-12-06 19:56:13 -08:00
Carl Lerche 22862739dd rt: yield_now defers task until after driver poll (#5223)
Previously, calling `task::yield_now().await` would yield the current
task to the scheduler, but the scheduler would poll it again before
polling the resource drivers. This behavior can result in starving the
resource drivers.

This patch creates a queue tracking yielded tasks. The scheduler
notifies those tasks **after** polling the resource drivers.

Refs: #5209
2022-11-30 14:21:08 -08:00
Carl Lerche 808d52563e ci: run tests on ARM and i686 using cross (#5196)
This patch updates CI to use `cross` to run Tokio tests on virtualized
ARM and i686 VMs. Because ipv6 doesn't work on Github action running in
a docker instance, those tests are disabled
2022-11-18 14:02:53 -08:00
Carl Lerche 53cba023da rt: fix accidental unsetting of current handle (#5178)
An earlier change updated `enter_runtime` to also set the current
handle. However, the change did not store the `SetCurrentGuard`, so the
"current handle" was immediately unset. This patch stores the
`SetCurrentGuard` in the `EnterRuntimeGuard`.

No existing test exposed this bug because all tests went via `Runtime`
instead of `Handle`. Currently, `Runtime` is still explicitly setting
the handle before entering runtime, so all tests still passed. A new
test is added that covers the case of calling `Handle::block_on` and
accessing the current handle.
2022-11-09 12:13:30 -08:00
Alice Ryhl fdc28bc883 coop: fix flaky coop test (#5074) 2022-10-05 12:55:02 +02:00
Carl Lerche a3411a412c rt, chore: rename internal scheduler types (#4945)
For historical reasons, the current-thread runtime's scheduler was named
BasicScheduler and the multi-thread runtime's scheduler were named
ThreadPool. This patch renames the schedulers to mirror the runtime
names to increase consistency. This patch also moves the scheduler
implementations into a new `runtime::scheduler` module.
2022-08-26 09:47:19 -07:00
Alice RyhlandTaiki Endo b2ada60e70 wasm: use build script to detect wasm (#4865)
Co-authored-by: Taiki Endo <[email protected]>
2022-07-26 11:26:54 +00:00
Josh Soref f3e340a35b chore: fix spelling mistakes (#4858)
Signed-off-by: Josh Soref <[email protected]>
2022-07-25 07:26:01 +00:00
Richard Zak 6d3f92dddc wasm: initial support for wasm32-wasi target (#4716)
This adds initial, unstable, support for the wasm32-wasi target. Not all of Tokio's
features are supported yet as WASI's non-blocking APIs are still limited.

Refs: tokio-rs/tokio#4827
2022-07-12 13:20:26 -07:00
Piotr Sarna 88e8c6239c task: add consume_budget for cooperative scheduling (#4498)
* task: add consume_budget for cooperative scheduling

For cpu-only computations that do not use any Tokio resources,
budgeting does not really kick in in order to yield and prevent
other tasks from starvation. The new mechanism - consume_budget,
performs a budget check, consumes a unit of it, and yields only
if the task exceeded the budget. That allows cpu-intenstive
computations to define points in the program which indicate that
some significant work was performed. It will yield only if the budget
is gone, which is a much better alternative to unconditional yielding,
which is a potentially heavy operation.

* tests: add a test case for task::consume_budget

The test case ensures that the task::consume_budget utility
actually burns budget and makes the task yield once the whole
budget is gone.
2022-05-30 09:15:54 +00:00
Alice Ryhl ddf2f5fdf6 rt: fix flaky wake_while_rt_is_dropping test (#4698) 2022-05-17 19:20:34 +02:00
Finomnis 454ac1c54f ci: enable ASAN in CI (#4696) 2022-05-16 16:57:03 +02:00
Thomas Orozco 05eeea570e coop: expose an unconstrained() opt-out (#3547) 2021-03-09 19:10:15 +01:00
Blas Rodriguez Irizar 117fc2ef3e tests: fix ping pong saturation (#3390) 2021-01-21 11:02:40 +01:00
Alice Ryhl 78f2340d25 tokio: remove prelude (#3299)
Closes: #3257
2020-12-19 11:42:24 -08:00
Kyle Kosic a85fdb884d runtime: test for shutdown_timeout(0) (#3196) 2020-11-29 21:30:19 +01:00
Carl Lerche 00b6127f2e rt: switch enter to an RAII guard (#2954) 2020-10-13 15:06:22 -07:00
8880222036 rt: Remove threaded_scheduler() and basic_scheduler() (#2876)
Co-authored-by: Alice Ryhl <[email protected]>
Co-authored-by: Carl Lerche <[email protected]>
2020-10-12 13:44:54 -04:00
Juan Alvarez 60d81bbe10 time: rename Delay future to Sleep (#2932) 2020-10-08 20:35:12 -07:00
bdonlanandBryan Donlan b704c53b9c chore: Fix clippy lints (#2931)
Closes: #2929

Co-authored-by: Bryan Donlan <[email protected]>
2020-10-08 17:14:39 -07:00
Carl Lerche 066965cd59 net: use &self with TcpListener::accept (#2919)
Uses the infrastructure added by #2828 to enable switching
`TcpListener::accept` to use `&self`.

This also switches `poll_accept` to use `&self`. While doing introduces
a hazard, `poll_*` style functions are considered low-level. Most users
will use the `async fn` variants which are more misuse-resistant.

TcpListener::incoming() is temporarily removed as it has the same
problem as `TcpSocket::by_ref()` and will be implemented later.
2020-10-08 12:12:56 -07:00
Juan Alvarez 53ccfc1fd6 time: introduce sleep and sleep_until functions (#2826) 2020-10-01 09:24:33 +02:00
Sean McArthur a0557840eb io: use intrusive wait list for I/O driver (#2828)
This refactors I/O registration in a few ways:

- Cleans up the cached readiness in `PollEvented`. This cache used to
  be helpful when readiness was a linked list of `*mut Node`s in
  `Registration`. Previous refactors have turned `Registration` into just
  an `AtomicUsize` holding the current readiness, so the cache is just
  extra work and complexity. Gone.
- Polling the `Registration` for readiness now gives a `ReadyEvent`,
  which includes the driver tick. This event must be passed back into
  `clear_readiness`, so that the readiness is only cleared from `Registration`
  if the tick hasn't changed. Previously, it was possible to clear the
  readiness even though another thread had *just* polled the driver and
  found the socket ready again.
- Registration now also contains an `async fn readiness`, which stores
  wakers in an instrusive linked list. This allows an unbounded number
  of tasks to register for readiness (previously, only 1 per direction (read
  and write)). By using the intrusive linked list, there is no concern of
  leaking the storage of the wakers, since they are stored inside the `async fn`
  and released when the future is dropped.
- Registration retains a `poll_readiness(Direction)` method, to support
  `AsyncRead` and `AsyncWrite`. They aren't able to use `async fn`s, and
  so there are 2 reserved slots for those methods.
- IO types where it makes sense to have multiple tasks waiting on them
  now take advantage of this new `async fn readiness`, such as `UdpSocket`
  and `UnixDatagram`.

Additionally, this makes the `io-driver` "feature" internal-only (no longer
documented, not part of public API), and adds a second internal-only
feature, `io-readiness`, to group together linked list part of registration
that is only used by some of the IO types.

After a bit of discussion, changing stream-based transports (like
`TcpStream`) to have `async fn read(&self)` is punted, since that
is likely too easy of a footgun to activate.

Refs: #2779, #2728
2020-09-23 13:02:15 -07:00
Lucio Franco f25f12d576 rt: Allow concurrent block_on's with basic_scheduler (#2804) 2020-09-23 14:35:10 -04:00
Lucio FrancoandEliza Weisman d600ab9a8f rt: Refactor Runtime::block_on to take &self (#2782)
Co-authored-by: Eliza Weisman <[email protected]>
2020-08-27 20:05:48 -04:00
Émile Grégoire 646fbae765 rt: fix potential leak during runtime shutdown (#2649)
JoinHandle of threads created by the pool are now tracked and properly joined at
shutdown. If the thread does not return within the timeout, then it's not joined and
left to the OS for cleanup.

Also, break a cycle between wakers held by the timer and the runtime.

Fixes #2641, #2535
2020-07-28 20:43:19 -07:00
Carl Lerche 98e7831479 net: fix OwnedWriteHalf behavior on drop (#2597)
Previously, dropping the Write handle would issue a `shutdown(Both)`. However,
shutting down the read half is not portable and not the correct action to take.

This changes the behavior of OwnedWriteHalf to only perform a `shutdown(Write)`
on drop.
2020-07-12 19:25:58 -07:00
Dan Burkert d8139fef7a Add Handle::block_on method (#2437) 2020-04-24 15:25:48 +03:00
Carl Lerche fa4fe9ef6f rt: fix queue regression (#2362)
The new queue uses `u8` to track offsets. Cursors are expected to wrap.
An operation was performed with `+` instead of `wrapping_add`. This was
not _obviously_ issue before as it is difficult to wrap a `usize` on
64bit platforms, but wrapping a `u8` is trivial.

The fix is to use `wrapping_add` instead of `+`. A new test is added
that catches the issue.

Fixes #2361
2020-04-02 07:52:02 -07:00
Carl Lerche caa7e180e4 rt: cap fifo scheduler slot to avoid starvation (#2349)
The work-stealing scheduler includes an optimization where each worker
includes a single slot to store the **last** scheduled task. Tasks in
scheduler's LIFO slot are executed next. This speeds up and reduces
latency with message passing patterns.

Previously, this optimization was susceptible to starving other tasks in
certain cases. If two tasks ping-ping between each other without ever
yielding, the worker would never execute other tasks.

An early PR (#2160) introduced a form of pre-emption. Each task is
allocated a per-poll operation budget. Tokio resources will return ready
until the budget is depleted, at which point, Tokio resources will
always return `Pending`.

This patch leverages the operation budget to limit the LIFO scheduler
optimization. When executing tasks from the LIFO slot, the budget is
**not** reset. Once the budget goes to zero, the task in the LIFO slot
is pushed to the back of the queue.
2020-03-28 13:55:12 -07:00
Carl Lerche 11acfbbea4 rt: add task join coop test (#2345)
Add test verifying that joining on a task consumes the caller's budget.
2020-03-26 22:17:48 -07:00
Carl Lerche a78b1c65cc rt: cleanup and simplify scheduler (scheduler v2.5) (#2273)
A refactor of the scheduler internals focusing on simplifying and
reducing unsafety. There are no fundamental logic changes.

* The state transitions of the core task component are refined and
reduced.
* `basic_scheduler` has most unsafety removed.
* `local_set` has most unsafety removed.
* `threaded_scheduler` limits most unsafety to its queue implementation.
2020-03-05 10:31:37 -08:00
Carl Lerche 9d6b99494b rt: add Runtime::shutdown_timeout (#2186)
Provides an API for forcing a runtime to shutdown even if there are
still running tasks.
2020-01-29 12:00:40 -08:00
Carl Lerche 6406328176 rt: fix threaded scheduler shutdown deadlock (#2074)
Previously, if an IO event was received during the runtime shutdown
process, it was possible to enter a deadlock. This was due to the
scheduler shutdown logic not expecting tasks to get scheduled once the
worker was in the shutdown process.

This patch fixes the deadlock by checking the queues for new tasks after
each call to park. If a new task is received, it is forcefully shutdown.

Fixes #2061
2020-01-08 21:23:10 -08:00
Linus Färnstrand dcfa895b51 chore: use just std instead of ::std in paths (#2049) 2020-01-06 10:04:21 -08:00
Carl Lerche adc5186ebd rt: fix storing Runtime in thread-local (#2011)
Storing a `Runtime` value in a thread-local resulted in a panic due to
the inability to access the parker.

This fixes the bug by skipping parking if it fails. In general, there
isn't much that we can do besides not parking.

Fixes #593
2019-12-22 13:03:44 -08:00
Carl Lerche 3d1b4b3058 rt: fix spawn_blocking from spawn_blocking (#2006)
Nested spawn_blocking calls would result in a panic due to the necessary
context not being setup. This patch sets the blocking pool context from
within a blocking pool.

Fixes #1982
2019-12-21 13:19:52 -08:00
Artem Vorotnikov d593c5b051 chore: remove benches and fix/work around clippy lints (#1952) 2019-12-13 22:01:47 -08:00
Carl Lerche a8a4a9f0fc blocking: fix spawn_blocking after shutdown (#1875)
The task handle needs to be shutdown explicitly and not dropped.

Closes #1853
2019-12-01 12:58:01 -08:00
Carl Lerche a2cfc877a7 rt: fix basic_scheduler notification bug (#1861)
The "global executor" thread-local is to track where to spawn new tasks,
**not** which scheduler is active on the current thread. This fixes a
bug with scheduling tasks on the basic_scheduler by tracking the
currently active basic_scheduler with a dedicated thread-local variable.

Fixes: #1851
2019-11-29 10:23:22 -08:00
Eliza Weisman 38e602f4d8 task: add LocalSet API for running !Send futures (#1733)
## Motivation

In earlier versions of `tokio`, the `current_thread::Runtime` type could
be used to run `!Send` futures. However, PR #1716 merged the
current-thread and threadpool runtimes into a single type, which can no
longer run `!Send` futures. There is still a need in some cases to
support futures that don't implement `Send`, and the `tokio-compat`
crate requires this in order to provide APIs that existed in `tokio`
0.1.

## Solution

This branch implements the API described by @carllerche in
https://github.com/tokio-rs/tokio/pull/1716#issuecomment-549496309. It
adds a new `LocalSet` type and `spawn_local` function to `tokio::task`.
The `LocalSet` type is used to group together a set of tasks which must
run on the same thread and don't implement `Send`. These are available
when a new "rt-util" feature flag is enabled.

Currently, the local task set is run by passing it a reference to a
`Runtime` and a future to `block_on`. In the future, we may also want
to investigate allowing spawned futures to construct their own local
task sets, which would be executed on the worker that the future is
executing on. 

In order to implement the new API, I've made some internal changes to
the `task` module and `Schedule` trait to support scheduling both `Send`
and `!Send` futures.

Signed-off-by: Eliza Weisman <[email protected]>
2019-11-26 17:03:18 -08:00
Carl Lerche 7b4c999341 default all feature flags to off (#1811)
Changes the set of `default` feature flags to `[]`. By default, only
core traits are included without specifying feature flags. This makes it
easier for users to pick the components they need.

For convenience, a `full` feature flag is included that includes all
components.

Tests are configured to require the `full` feature. Testing individual
feature flags will need to be moved to a separate crate.

Closes #1791
2019-11-22 15:55:10 -08:00
Carl Lerche 8546ff826d runtime: cleanup and add config options (#1807)
* runtime: cleanup and add config options

This patch finishes the cleanup as part of the transition to Tokio 0.2.
A number of changes were made to take advantage of having all Tokio
types in a single crate. Also, fixes using Tokio types from
`spawn_blocking`.

* Many threads, one resource driver

Previously, in the threaded scheduler, a resource driver (mio::Poll /
timer combo) was created per thread. This was more or less fine, except
it required balancing across the available drivers. When using a
resource driver from **outside** of the thread pool, balancing is
tricky. The change was original done to avoid having a dedicated driver
thread.

Now, instead of creating many resource drivers, a single resource driver
is used. Each scheduler thread will attempt to "lock" the resource
driver before parking on it. If the resource driver is already locked,
the thread uses a condition variable to park. Contention should remain
low as, under load, the scheduler avoids using the drivers.

* Add configuration options to enable I/O / time

New configuration options are added to `runtime::Builder` to allow
enabling I/O and time drivers on a runtime instance basis. This is
useful when wanting to create lightweight runtime instances to execute
compute only tasks.

* Bug fixes

The condition variable parker is updated to the same algorithm used in
`std`. This is motivated by some potential deadlock cases discovered by
`loom`.

The basic scheduler is fixed to fairly schedule tasks. `push_front` was
accidentally used instead of `push_back`.

I/O, time, and spawning now work from within `spawn_blocking` closures.

* Misc cleanup

The threaded scheduler is no longer generic over `P :Park`. Instead, it
is hard coded to a specific parker. Tests, including loom tests, are
updated to use `Runtime` directly. This provides greater coverage.

The `blocking` module is moved back into `runtime` as all usage is
within `runtime` itself.
2019-11-21 23:28:39 -08:00
Carl Lerche 4d19a99937 runtime: set spawn context on enter (#1780) 2019-11-16 22:24:28 -08:00
Carl Lerche 19f1fc36bd task: return JoinHandle from spawn (#1777)
`tokio::spawn` now returns a `JoinHandle` to obtain the result of the task:

Closes #887.
2019-11-16 08:28:34 -08:00
Carl Lerche 3f0eabe779 runtime: rename current_thread -> basic_scheduler (#1769)
It no longer supports executing !Send futures. The use case for
It is wanting a “light” runtime. There will be “local” task execution
using a different strategy coming later.

This patch also renames `thread_pool` -> `threaded_scheduler`, but
only in public APIs for now.
2019-11-16 07:19:45 -08:00
Carl Lerche 8a7e57786a Limit futures dependency to Stream via feature flag (#1774)
In an effort to reach API stability, the `tokio` crate is shedding its
_public_ dependencies on crates that are either a) do not provide a
stable (1.0+) release with longevity guarantees or b) match the `tokio`
release cadence. Of course, implementing `std` traits fits the
requirements.

The on exception, for now, is the `Stream` trait found in `futures_core`.
It is expected that this trait will not change much and be moved into `std.
Since Tokio is not yet going reaching 1.0, I feel that it is acceptable to maintain
a dependency on this trait given how foundational it is.

Since the `Stream` implementation is optional, types that are logically
streams provide `async fn next_*` functions to obtain the next value.
Avoiding the `next()` name prevents fn conflicts with `StreamExt::next()`.

Additionally, some misc cleanup is also done:

- `tokio::io::io` -> `tokio::io::util`.
- `delay` -> `delay_until`.
- `Timeout::new` -> `timeout(...)`.
- `signal::ctrl_c()` returns a future instead of a stream.
- `{tcp,unix}::Incoming` is removed (due to lack of `Stream` trait).
- `time::Throttle` is removed (due to lack of `Stream` trait).
-  Fix: `mpsc::UnboundedSender::send(&self)` (no more conflict with `Sink` fns).
2019-11-15 22:11:13 -08:00