Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

Async/await does not make CPU-bound code preemptible. In Tokio, a task that runs a long stretch of synchronous computation without reaching an .await can occupy its worker and prevent other tasks assigned to that worker from progressing. Keep short work in the async task; move bounded blocking work to spawn_blocking; and use explicit limits or a CPU-oriented pool such as Rayon when CPU-heavy jobs need controlled parallelism.

Why CPU work inside an async function can block other tasks

An async fn is not automatically nonblocking. Tokio schedules tasks cooperatively: it can switch the task running on a worker at .await points. A computation that keeps running synchronously without reaching one does not give Tokio that scheduling opportunity. The Tokio project documentation puts it plainly: “However, this kind of swapping can only happen at .await points, so code that spends a long time without reaching an .await will prevent other tasks from running.” Tokio library documentation

This is a worker-level stall, not proof that all async code is single-threaded. Other workers can continue running tasks, but tasks that depend on the occupied worker may be delayed. Tokio’s fairness guarantee assumes, among other conditions, that each task poll returns within bounded time and that no task blocks its thread; it does not guarantee prompt progress when a task monopolizes a worker. Tokio runtime documentation

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choose an execution boundary based on the work

Approach Best fit Important limitation
Compute directly in an async task Short work or work that regularly reaches .await. A long synchronous stretch can block progress for other tasks on that worker.
tokio::task::spawn_blocking Bounded blocking operations that eventually finish; the closure’s result can be awaited. Further jobs queue after the configured blocking-thread limit. The default limit is large, and started jobs cannot be aborted, so CPU-heavy submissions may need an explicit concurrency cap.
Rayon thread pool CPU-bound parallel work where a specialized CPU executor or an explicit CPU worker pool is useful. Pool sizing and workload need deliberate configuration; its default is not an optimal setting for every deployment.

When to use Tokio’s spawn_blocking

spawn_blocking runs a closure on a thread where blocking is acceptable, rather than occupying a Tokio core worker with synchronous work. Tokio describes it as intended for non-async operations that eventually finish on their own. The closure can return a value that the async caller awaits. Tokio spawn_blocking API documentation

The blocking pool grows on demand up to a configured maximum; calls made after that maximum is reached are queued. Because Tokio’s default upper limit is high, simply submitting many CPU-heavy jobs to spawn_blocking is not a reliable way to cap CPU concurrency. Tokio recommends using a semaphore or another synchronization primitive when you need to limit simultaneous computations. Tokio spawn_blocking API documentation

Account for cancellation and shutdown

A started spawn_blocking task cannot be aborted. Runtime shutdown waits for started blocking jobs unless a shutdown timeout stops the wait; the timeout does not cancel the work itself. This matters when CPU work is tied to a request or when a service must shut down promptly: design the job’s own lifecycle and cancellation checks rather than assuming the runtime can stop it. Tokio spawn_blocking API documentation

Rank #2
MICRO CENTER AMD 9900X Processor with ASUS ROG Strix B650A WiFi Motherboard
  • AMD Ryzen 9 9900X Desktop Processor, 12-Core, 24-Thread, 5.6 GHz Max Boost, Unlocked for overclocking, L2+L3 76 MB cache, DDR5, Default TDP 120W. The world's best gaming desktop processor that can deliver ultra-fast 100+ FPS performance in the world's most popular games
  • For the state-of-the-art Socket AM5 platform, can support PCIe 5.0 on select 600 Series motherboards. OS Support: Windows 11/ 10-64-Bit Edition. Cooler & Thermal Solution (PIB) not included. AMD Radeon Graphics Integrated
  • ASUS ROG Strix B650-A Gaming WiFi Motherboard, ATX Form Factor, Support Dual Channel Memory DDR5 up to 192GB, 3 x M.2 slots and 4 x SATA 6Gb/s ports, Wi-Fi 6E, Bluetooth v5.2, USB 3.2 Gen 2x2 Type C, USB 3.2 Gen 2 Type C & Type A, Windows 11 64-bit Support
  • AMD Socket AM5(LGA 1718): Ready for AMD Ryzen 7000 Series desktop processors.Audio : High quality 120 dB SNR stereo playback output and 113 dB SNR recording input;/ Robust Power Solution: 12 + 2 power stages with 8+4 pin ProCool power connectors, high-quality alloy chokes, and durable capacitors to support multi-core processors
  • Optimized Thermal Design: Massive VRM heatsinks with strategically cut airflow channels and high conductivity thermal pads;/ Next-Gen M.2 Support: One PCIe 5.0 M.2 slot and two PCIe 4.0 M.2 slots, all with heatsinks to maximize performance;/ Advanced Connectivity: One USB 3.2 Gen 2x2 Type-C and eight additional rear USB ports, USB 3.2 Gen 2 Type-C front-panel connector, HDMI 2.1, DisplayPort 1.4, and one PCIe 4.0 x16 SafeSlot

For indefinitely running or persistent loops, Tokio’s guidance is to use a dedicated OS thread rather than treating spawn_blocking as a home for work that never completes. That is a different case from dispatching bounded CPU jobs to a pool.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

When Rayon is a better fit

Rayon provides a CPU-oriented worker pool with work stealing: workers can take queued work from one another. By default, the pool uses as many threads as CPUs available to the process; on a hyperthreaded system, that generally means logical CPUs, not physical cores. You can configure the count with RAYON_NUM_THREADS or with ThreadPoolBuilder::build_global. Rayon documentation

Tokio’s library documentation points to Rayon as an option when CPU-bound work needs a specialized executor. To send a result back to Tokio, the documented pattern is to use a one-shot channel: run the CPU work on Rayon, send its result through the channel, and await the receiver in the async task. Tokio library documentation

Rayon provides a pool and scheduling behavior, not a guarantee of faster execution. The appropriate pool size and whether parallelism helps depend on the workload and deployment; measure the application you intend to run before choosing production settings.

How to decide for a real workload

  1. Keep it in the async task if the work is short or naturally yields often. Avoid long CPU loops between await points.
  2. Use spawn_blocking for bounded blocking work that completes, especially when moving it off a Tokio core worker is the main need.
  3. Set an admission limit if many CPU-heavy jobs may arrive together. A semaphore can limit how many jobs enter the blocking pool at once.
  4. Consider Rayon when CPU-bound parallelism needs a dedicated worker pool or when the work is structured to benefit from parallel execution.
  5. Handle lifecycle explicitly. Started blocking jobs cannot be aborted; long-lived loops belong on dedicated OS threads, and shutdown behavior should account for work still running.
  6. Benchmark the actual application. Neither the Tokio nor Rayon documentation establishes one pool split or thread count as best for every workload.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Thread defaults are configuration, not performance promises

Tokio’s library documentation describes core threads for asynchronous code and blocking threads created on demand for work that would otherwise block tasks. It documents a default of one core thread per CPU core and says the core-thread count can be overridden with TOKIO_WORKER_THREADS. Treat these defaults as version-sensitive: check the documentation for the Tokio version deployed by your application. Tokio library documentation

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Best Value
INTEL CM8064401807100 Xeon E5-2697 v3 Fourteen-Core Haswell Processor 2.6GHz 9.6GT/s 35MB LGA 2011-v3 CPU, OEM OEM (Renewed)
  • Certified Refurbished Quality: This product is tested and certified to look and work like new, with the refurbishing process including functionality testing, basic cleaning, inspection, and repackaging, ships with all relevant accessories and a minimum 90-day warranty
  • Processor Specifications: Intel Xeon E5-2697 v3 Fourteen-Core Haswell Processor featuring 2.6GHz base clock speed, 9.6GT/s QPI speed, and 35MB cache memory with LGA 2011-v3 socket compatibility
  • High-Performance Computing: Fourteen physical cores deliver exceptional multi-threaded performance for demanding server and workstation applications requiring substantial processing power
  • Advanced Architecture: Built on Intel's Haswell microarchitecture providing improved performance per watt and enhanced instruction set capabilities for enterprise-level computing tasks
  • Technical Details: 145W TDP design with model number SR1XF, engineered for professional workstations and server environments requiring reliable high-core-count processing capabilities

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.