#worker-thread #future #tokio #task-scheduler

tokio-threadpool

基于工作窃取线程池的任务调度器

21 个版本

0.2.0-alpha.12019 年 8 月 8 日
0.1.18 2020 年 2 月 4 日
0.1.17 2019 年 12 月 4 日
0.1.16 2019 年 9 月 30 日
0.1.2 2018 年 3 月 30 日

27#task-scheduler

Download history 36281/week @ 2024-03-14 33516/week @ 2024-03-21 34964/week @ 2024-03-28 28661/week @ 2024-04-04 31272/week @ 2024-04-11 30453/week @ 2024-04-18 35564/week @ 2024-04-25 33870/week @ 2024-05-02 36727/week @ 2024-05-09 35490/week @ 2024-05-16 33880/week @ 2024-05-23 39088/week @ 2024-05-30 39029/week @ 2024-06-06 33559/week @ 2024-06-13 31946/week @ 2024-06-20 23510/week @ 2024-06-27

135,626 每月下载量
少于 18 crates 中使用

MIT 许可证

570KB
10K SLoC

Tokio 线程池

一个库,用于在多个线程池中并发调度执行 future。

许可证

该项目受 MIT 许可证 的许可。

贡献

除非你明确说明,否则你提交的任何贡献,只要有意提交到 Tokio,都应按 MIT 许可,没有任何附加条款或条件。


lib.rs:

用于执行 future 的工作窃取线程池。

Tokio 线程池支持在多个 CPU 核心上调度 future 并处理它们。它针对 Tokio 的主要用例进行了优化,即许多独立的任务,计算有限且大多数任务都在等待 I/O。通常,用户不会直接创建 ThreadPool 实例,而是通过 runtime 使用它。

ThreadPool 结构管理两套线程

  • 工作线程。
  • 备份线程。

工作线程用于使用工作窃取策略调度 future。另一方面,备份线程仅用于支持 blocking API。线程将在这两套之间转换。

工作窃取策略的优点是最小化线程间的协调。线程池试图在不通过线程进行通信的情况下尽可能多地取得进展。

工作线程概述

每个工作线程有两个队列:一个双端队列和一个 mpsc 通道。双端队列是工作线程上安排运行的任务的默认队列。任务只能由工作线程推送到双端队列,但其他工作线程可以“窃取”该队列中的任务。mpsc 通道用于在池外部提交 future。

只要线程池没有被关闭,工作线程就会在一个循环中运行。每次循环,它都会消耗其mpsc通道上的所有任务,并将其推送到deque中。然后,它从deque中弹出任务并执行它们。

如果工作线程没有工作,即两个队列都为空。它会尝试窃取任务。为此,它会随机扫描其他工作线程的deque并尝试弹出任务。如果没有找到可窃取的工作,该线程将进入休眠状态。

当工作线程检测到池已关闭时,它会退出循环,清理其状态,并关闭线程。

线程池初始化

注意,用户通常将使用由 runtime 创建的线程池。

默认情况下,在创建时不会生成任何线程。相反,当新的futures生成时,池首先检查是否有足够的活跃工作线程。如果没有,将生成一个新的工作线程。

生成futures

生成行为取决于futures是在工作线程或线程内部生成,还是从外部句柄生成。

当在外部线程池中生成futures时,当前策略是随机选择一个工作线程来提交任务。然后,将任务推送到该工作线程的mpsc通道。

当在工作线程上生成futures时,任务将被推送到当前工作线程deque的末尾。

阻塞注释策略

blocking 函数用于注释执行阻塞操作的代码段,无论是通过发出阻塞系统调用还是执行任何长时间运行的CPU密集型计算。

处理阻塞闭包的策略是将工作线程传递给新线程。这意味着将 dequempsc 传递。一旦完成,新线程将继续处理工作队列,而原始线程可以阻塞。一旦它完成处理阻塞的futures,该线程没有更多工作,并被插入到备用池中。这使得它可供遇到 blocking 调用的其他工作线程使用。

依赖项

~1.5MB
~25K SLoC