就超标量流水线乱序 exec CPU 中的单条指令而言,吞吐量与延迟非常重要,因为 CPU 试图从必须执行的指令流中提取并行性就好像 按串行程序顺序。例如,请参阅Assembly - How to score a CPU instruction by latency and throughput 和我在latency vs throughput in intel intrinsics 上的答案底部。
就在比几个时钟周期更长的时间尺度上影响吞吐量与延迟的操作系统决策而言,这是一个完全不同的问题。
其中一个主要因素是选择如何使用可用的物理 RAM,以及是否将不经常使用的代码/数据换出(到交换文件)以腾出更多空间来缓存磁盘文件。 (例如,Linux 的 vm.swappiness 被广泛认为是在服务器和桌面之间设置不同的关键可调参数。https://unix.stackexchange.com/questions/88693/why-is-swappiness-set-to-60-by-default)。
如果您在该进程的许多页面已被调出时使用 alt-tab 键切换到窗口,则该进程需要一些时间才能重绘其窗口。 (多个硬页面错误,可能会非常慢,尤其是在旋转磁盘而不是 SSD 上进行分页时。)因此,为了优化延迟,您希望内核不要积极地从正在运行的进程中换出页面,即使它们已经空闲了几个小时。如果这些页面是空闲的,则可以通过充当缓冲区/缓存来提高其他进程的吞吐量。
一个相关因素是 I/O 调度:尝试将 IO 请求组合在一起以最小化 HD 寻道时间(以获得更高的吞吐量和更低的平均延迟),但有时会以延迟一些请求为代价(更高的最坏-案例延迟)。例如,Linux 有很多可供选择,包括截止日期、完全公平排队 (CFQ) 和原始电梯(仅按位置对请求进行分组,不考虑公平或延迟)。 https://wiki.archlinux.org/title/improving_performance#Input/output_schedulers
CPU 调度 也是一个因素:上下文切换会损害吞吐量,因为它本身需要时间,并且缓存对于此 CPU 上的新任务可能很冷。您还必须运行内核的 schedule() 函数来决定接下来要运行哪个任务,这样会占用一些实际工作的时间。
为了最大程度地减少延迟(例如,在将套接字消息发送到进程与在其 poll 或 select 系统调用返回时唤醒之间),您需要一个较短的时间片,例如 Linux HZ=1000。 (定时器每 1 ms 中断一次以运行调度程序)。并且您希望能够抢占内核本身,而不是等到内核准备好返回旧用户空间时才考虑运行不同用户空间任务的可能性。
但是这些都不能帮助提高吞吐量,而且实际上会受到伤害(假设工作负载有足够的并行性,不会成为延迟瓶颈)。因此,HZ=100 是“服务器”Linux 构建的默认值,而“桌面”构建上的 1000 是为交互使用而调整的。 (现代 Linux 可以“无滴答”,根本不在每个内核上使用固定的定时器中断,而是根据具体情况决定何时安排下一个中断。)
实时内核更进一步,将更多时间花在更细粒度的锁定和类似的东西上,以启用暂停工作并稍后返回以最小化中断延迟和它之间的其他延迟是时候做某事并真正开始做那件事。 (有适用于 Linux 的实时补丁,也有完全独立的内核,用于实时操作。)
如果你有一个嵌入式系统控制电机或其他东西,你绝对需要硬实时延迟保证,它永远从一个中断引脚被断言到中断的时间不会超过 1 毫秒处理程序开始运行。
(设计系统以使这些保证成为可能通常会以吞吐量为代价。例如,显然您必须固定一些内存以使其不可交换,如果我们谈论的是用户空间,甚至使其无法用于缓存如果它几天都没有动过。)