收集性能数据

创建查询并向其添加计数器后,调用 PdhCollectQueryData 函数以检索查询中所有计数器的当前原始数据。

许多计数器(如速率计数器)需要两个数据样本来计算格式化的数据值。 PDH 维护当前样本和以前收集的样本的数据。 以下过程介绍如何收集需要两个样本来计算可显示值的计数器值。

要收集需要两个样本来计算可显示值的计数器值

  1. 调用 PdhCollectQueryData 以收集第一个样本。
  2. 调用 Sleep 函数以在集合之间至少等待一秒。
  3. 再次调用 PdhCollectQueryData 以收集第二个样本。
  4. 调用 PdhGetFormattedCounterValue 函数以计算可显示的值。
  5. 重复步骤 2 到 4。

作为自行实现等待期的替代方法,可以调用 PdhCollectQueryDataEx 函数,它会创建等待指定时间的计时线程,收集样本,然后触发应用程序定义的事件。

如果要从日志文件查询性能数据,还可以定义时间范围。 时间范围将查询限制为在时间范围内收集的样本(每个样本都包含收集时间的时间戳)。 有关如何设置和检索时间范围的详细信息,请参阅设置查询的时间范围

如果要收集性能数据并将其写入日志文件,则需要调用 PdhUpdateLog 函数,而不是调用 PdhCollectQueryData。 有关详细信息,请参阅使用日志文件将性能数据写入日志文件

有关计算可显示的样本值的详细信息,请参阅“显示性能数据”。

了解多个处理器计数器

某些性能计数器专为单处理器系统设计,对于多处理器计算机可能不准确。 例如,某个进程的限制为单个处理器的百分之 100,但是,其线程可以使用多个处理器,总计超过百分之 100。

“\Processor(_Total)\% Processor Time”计数器值是所有处理器的平均使用率。 例如,如果你有两个处理器,一个为百分之 100,另一个为百分之 0,则此计数器将报告百分之 50。 因此,范围是从 0 到 100。

“\Process(X)\% Processor Time”(其中 X 是进程名称),计数器值是进程 X 的所有线程的处理器使用率总和。例如,在具有两个处理器的计算机中,如果某个进程有两个线程,一个占用一个 CPU 的百分之 75,另一个占用另一个 CPU 的百分之 80,则此计数器将报告百分之 155。 此计数器的范围是从 0 到 100 * ProcessorCount。

使用 Process 计数器集时,可以在 CPU 使用率的预期值范围之外接收值。 要计算 CPU 使用率的百分比,PDH 需要两个样本(每个样本都有原始值和时间戳)。 由于 PDH 仅使用实例名称来匹配进程,因此有时可能会混合来自不同进程的样本。 例如,如果正在对具有相同实例名称的三个进程进行采样,并在第三个样本后终止了其中一个进程,则另一个进程将移到由已终止的进程空出来的槽。 因此,格式化计数器会在设置第四个样本的格式时提供不正确的值,因为它会使用已终止进程中的第三个样本,以及移到已终止进程的槽中的进程的第四个样本。

下表显示了如果在收集数据时进程终止,就会发生这种情况。 该表显示了三个进程 X 的实例的五个计数器值样本。样本每隔一秒收集一次。 收集完第三个样本后,槽 1 中的进程 X 被终止。 当槽 1 中的进程 X 被终止时,槽 2 中的进程 X 会移动到槽 1。 在槽 2 中收集进程 X 的第四个样本时,第一个值现在是 20 而不是 1,000,第二个值为 1,500。 设置计数器值的格式时,你将获得 1,480 毫秒,而不是预期的 500 毫秒。 设置第五个样本值的格式时,你应获得预期值。

示例 进程 X 的槽 0 进程 X 的槽 1 进程 X 的槽 2
示例 1 0 0 0
示例 2 20 10 500
示例 3 40 20 1,000
示例 4 60 1,500(从之前的槽 2) 不适用。 现在收集在槽 1 中。
示例 5 80 2,000 不适用。 现在收集在槽 1 中。

提示

从 Windows 11 开始,可以使用新的 Process V2 计数器集来避免此问题。 Process V2 计数器集包括实例名称中的进程 ID。 这可以避免在原始 Process 计数器集中出现的不一致结果。