Windows 操作系统 Quantum 与 SQL 操作系统 Quantum

Joh*_* N. 21 sql-server

简单的问题

SQL Server Quantum (4 ms) 如何与 Server OS Quantum(通常:187.5 ms)同步?

简单问题解释

在使用 184 ms 的 OS 量程后(对应于 46 个完整的 SQL 量程),OS 量程有 3.5 ms 的时间,然后它必须将调度移交给不同的进程。SQL 操作系统启动一个时间段(4 毫秒),在 3.5 毫秒后,操作系统时间段决定停止当前的 SQL 操作系统线程,该线程在它产生计划之前还有 0.5 毫秒。现在会发生什么?


深入了解 OS Quantum

在接下来的几节中,我将写出迄今为止我所发现的关于 OS 量程以及如何计算量程的持续时间。操作系统“量子”的持续时间基于“滴答”,而“滴答”本身的持续时间基于“时钟间隔”,通常为 15.625000 毫秒。但是让我详细说明一下......

打钩

在博客文章Know Thy Tick 中,作者 Jim 解释了时钟间隔(又名“滴答”)的基础知识以及它们的用途。

当我读到诸如“时钟间隔……对于大多数 x86 多处理器大约为 15 毫秒”之类的内容时,我不得不确定我的时钟或“滴答”间隔的值。幸运的是,我在书中读到了这句话,Windows Internals第四版提供了一个参考来帮助我解决我的痛苦。... 上述书籍的作者 Mark Russinovich 慷慨地在其网站上提供了ClockRes实用程序。运行此实用程序,我能够确定我的 x86 多处理器 PC 上的时钟间隔为 15.625000 毫秒。有趣,但我好奇的头脑想知道更多。

量子

文章作者在他的第二篇文章中继续解释 那...

当然,tick 间隔重要的真正原因是它会影响线程调度。Windows 调度程序在允许另一个具有相同优先级的任务运行之前,为每个线程提供一个“时间”来执行。调度程序分配给线程的量程是滴答间隔的倍数。为特定线程选择的特定量子值有点超出我想在本文中讨论的内容。

好的,所以我知道什么是量子,但不知道量子将运行多长时间。

现在,让我们检查 XPe 中前台线程的默认量子值。在这种情况下,Windows 调度程序分配 18 或 6 个滴答间隔。(是的,要将量子转换为滴答间隔,必须除以 3。...,但倍数的原因是允许调度程序能够“收费”执行导致线程挂起的操作的线程。)

我们现在知道时钟间隔 (tick) 应该在 15.625000 ms 左右,并且在默认量子为 18 的 Windows 桌面操作系统上,这将导致 6 个滴答声或 93.750000 ms (18 / 3 * 15.625000 ms)。

在 Windows Server 操作系统上,默认量程不同。“处理器调度”设置设置为“后台服务”

可以通过“系统设置 | 高级(选项卡)| 性能(部分)| 设置...”找到此设置,这将打开“性能选项 | 高级(选项卡)| 处理器调度”

默认量子设置为 36(背景)到 36(前景)。量子更大,因此更长。这是 Windows 桌面操作系统上 18(6 滴答)量子前景设置的 93.750000 毫秒的两倍,在为后台服务设置的服务器操作系统上大约为 187.500000 毫秒。

观察/解释

当您在服务器或桌面上将设置从“后台服务”更改为“应用程序”时,注册表中的HKLM\SYSTEM\CurrentControlSet\Control\PriorityControl\Win32PrioritySeparation项将从 0x18 更改为 0x02。0x02 的默认量子值是多少?这可以在评论中找到:

值 0x02 意味着“Short vs. Long”和“Variable vs. Fixed”字段是操作系统的默认值。

XPe 和 XP Pro 的这些字段的默认值是:Short & Variable,这与设置以下位附加位相同:0x24。

将此值与 0x02 进行 OR 运算得到 0x26,您将在本文的表格中找到该值。

参考:评论“掌握你的量子”(MSDN 博客)

同一篇文章中解释量子设置的表格:

Win32PrioritySeparation   Foreground   Background
0x28, 0x29, 0x2A                  18           18
0x18, 0x19, 0x1A                  36           36
0x24                               6            6
0x25, 0x14                        12            6
0x26                              18            6
0x15                              24            6
0x16                              36            6
Run Code Online (Sandbox Code Playgroud)

OS Quantum 的简短摘要

根据以上信息和文章引用,我们知道量程不是固定大小,而是源自系统属性中的操作系统设置。量程因Win32PrioritySeparation注册表中的设置而异,该设置通常对应于“系统属性”(“后台服务”或“应用程序”)中的设置之一。

操作系统级别的量子是

  • 对于“应用程序”设置
    • 18(即 6 个滴答声)用于前台应用程序(93.75 毫秒)
    • 6(2 滴答)用于后台应用程序(31.25 毫秒)
  • 对于“后台服务”设置
    • 36(即 18 个滴答声)用于前台应用程序(187.5 毫秒)
    • 36(即 18 滴答声)用于后台应用程序(187.5 毫秒)

所以现在我们知道要针对后台服务优化的 Windows Server 设置上的操作系统量程是......

36 / 3 * 15.625000 ms = 187.5 ms
Run Code Online (Sandbox Code Playgroud)

SQL 操作系统量子

本节列出了我在 SQL OS 量子上发现的内容...

SOS_SCHEDULER_YIELD 等待类型

来自 Paul Randall 对 SOS_SCHEDULER_YIELD 等待类型的描述:

这种等待类型是当一个线程能够执行其完整的线程量程(在所有版本的 SQL Server 中为 4 毫秒,不可更改),因此自愿产生调度程序,移动到其调度程序中 Runnable 队列的底部。

参考:SOS_SCHEDULER_YIELD(SQLSkills.com 等待类型)

SQL Server DMV 中的调度程序

在有关 sys.dm_os_schedulers DMV 的 SQL Server DMV 的说明中。

[...] Windows 使用抢占式调度机制,并为每个线程分配 CPU 时间量,当一个线程消耗其量时,它被发送到队列,其他线程被授予执行权。

相反,当线程可以自愿放弃时间时,SQL Server 使用协作调度机制(当您具有 SOS_SCHEDULER_YIELD 等待类型时,您可以看到这种行为)。这允许 SQL Server 优化 CPU 利用率,因为当线程收到执行信号但尚未准备好运行时,它可以让出自己的时间量以有利于其他线程

参考:了解 SQL Server 调度程序、工作线程和任务(MSSQLTips.com)

检测 SQL Server CPU 压力

这是一篇关于 SQL Server 中 CPU 压力的文章的一小部分。

当一个任务自愿让出调度程序供其他任务执行时发生。在此等待期间,任务正在等待更新其量程

参考:检测 SQL Server CPU 压力(MSSQLTips.com)

sys.dm_os_schedulers (Microsoft Docs)

我想下面的引用是我能找到的关于 SQL OS 量子的最重要的信息片段:

quantum_length_us bigint  Identified for informational purposes only. 
                          Not supported. Future compatibility is not guaranteed. 
                          Exposes the scheduler quantum used by SQLOS.
Run Code Online (Sandbox Code Playgroud)

参考:sys.dm_os_schedulers (Transact-SQL) (Microsoft | Docs)


我的难题

服务器操作系统量子调节 SQL Server 服务被授予执行“任务”的时间。SQL Server OS Quantum 定义为 4 毫秒。如果我将 187.5 毫秒除以 4 毫秒,则剩下 3.5 毫秒。

我们甚至还没有开始讨论何时将时钟间隔设置为默认值 15.625000 毫秒以外的其他值......

简单的问题

SQL Server Quantum (4 ms) 如何与 Server OS Quantum(通常:187.5 ms)同步?

简单问题解释

在使用 184 ms 的 OS 量程后(对应于 46 个完整的 SQL 量程),OS 量程有 3.5 ms 的时间,然后它必须将调度移交给不同的进程。SQL 操作系统启动一个时间段(4 毫秒),在 3.5 毫秒后,操作系统时间段决定停止当前的 SQL 操作系统线程,该线程在它产生计划之前还有 0.5 毫秒。现在会发生什么?

Dav*_*oft 14

尽管调度程序不是抢占式的,但 SQL Server 调度程序仍然遵循量程的概念。SQL Server 任务不是被操作系统强制放弃 CPU,而是可以定期请求放入等待队列,如果它们已经超过内部定义的 4 毫秒时间段并且不在操作中间无法停止,他们自愿放弃CPU。

-“ Microsoft SQL Server 2012 Internals ”,Kalen Delaney 等。阿尔。pp38

-第 2 章“SQLOS”乔纳森·凯哈亚斯

因此,SQL Server 内部的“量子”概念更像是编程任务的“指南”。IE 当你写一个任务时,比如一个执行表扫描的任务,如果你没有碰到任何页面闩锁、IO 闩锁或锁等待一段时间,你应该停止你正在做的事情并要求成为放回可运行队列,以防有其他任务在等待。

但是这要由任务程序员来实现,对于每种任务,它可能不会恰好是4ms。例如,表扫描任务可能会根据扫描的页面数使用简单的启发式方法来实现让步。

所以

SQL 操作系统启动一个时间段(4 毫秒),在 3.5 毫秒后,操作系统时间段决定停止当前的 SQL 操作系统线程,该线程在它产生计划之前还有 0.5 毫秒。现在会发生什么?

如果 SQL Server 线程在任务运行时被 Windows 抢占,它将被暂停,并且当它的线程下一次被调度到 CPU 上时,它将从上次中断的地方继续。据推测,它会继续消耗其 4ms 量子的余额,因为它不知道有任何区别。但同样,yield 行为是任务的实现细节,而不是 SQLOS 的行为,因此不同的任务在这里可能表现不同。


小智 5

回答最初作为评论留下的贡献

SQL Server Quantum (4 ms) 如何与 Server OS Quantum(通常:187.5 ms)同步?

事实并非如此,而且 SQL Server 不使用抢占式调度。工作项预计会达到屈服点,如果没有达到,您将获得诸如NONYIELDING调度程序之类的东西。没有平价。SQL Server 不分配时间。它使某些线程对 Windows 具有吸引力以进行调度并且 Windows 调度它们。量子只是一段时间的命名法。就是这样。SQL Server 不是先发制人的,它是任何正在运行的代码的责任。–肖恩·加拉迪

当操作系统量程到期时,线程会被强制取消调度。这对 SQL Server 是透明的。SQLOS 无法检测何时发生这种情况。没有 Win32 API。调度对用户模式线程是透明的。Windows 调度程序不知道也不关心用户模式线程在做什么。Windows 只看到可运行的线程,并让它们运行直到它们的 OS 量程结束或直到它们被阻塞。- USR

在Nikola Dimitrijevic在如何处理 SQL Server 中过多的 SOS_SCHEDULER_YIELD 等待类型值中,术语“量子”本质上是指“任务实际花费分配给工作人员的时间”,但这与 Windows 量子不同,这是一段时间后,操作系统将从 CPU 中删除线程。它们只是不同的概念。如果操作系统因为已达到操作系统量程而强制线程结束执行,则会发生上下文切换。SQL Server 的线程被挂起,就像任何其他程序一样。–大卫布朗 - 微软George.Palacios


文档摘录:Inside the SQL Server 2000 User Mode Scheduler(为 SQL Server 2000 编写,但仍然相关):

抢先与合作任务

相比之下,UMS 依靠线程来自动让步。UMS 采取它所做的方法是为了避免在绝对必要的情况下涉及 Windows 内核。在一个可以依靠工作线程在应该让出时产生的系统中,协作调度程序实际上比抢占式调度程序更有效,因为调度过程可以根据应用程序的特定需求进行定制。正如我之前所说,UMS 比操作系统更了解 SQL Server 的调度需求。

UMS 如何接管调度

如果 UMS 要处理 SQL Server 的调度需求而不是允许 Windows 这样做,则 UMS 必须以某种方式阻止操作系统执行它对每个其他进程所做的事情:在它认为合适的情况下在系统处理器上和外调度线程。你如何在抢占式操作系统中做到这一点?UMS 通过使用 Windows 事件对象的一些巧妙技巧实现了这一点。UMS 下的每个线程都有一个关联的事件对象。出于调度的目的,Windows 会忽略它认为不可行的线程——因为它们处于无限等待状态而无法运行的线程。知道这一点后,UMS 通过让线程在其相应的事件对象上调用WaitForSingleObject并将超时值传递给INFINITE来将不希望被调度的线程置于睡眠状态。

为了防止 Windows 在同一个处理器上调度多个线程,从而导致上下文切换的开销和费用,UMS 尝试让每个处理器只保持一个线程可行——也就是说,不是处于无限等待状态。