跳转到内容

延迟测量与 PresentMon

本页内容

PCBenchmarkX 单独测量内部处理延迟和帧输出延迟。这些软件指标并不描述从鼠标点击到屏幕像素发光的完整路径。完整的测量循环在方法论中描述。

恒定流以8-12 毫秒的确定性间隔生成信号。如果 Windows 允许,它会创建一个高精度等待定时器;否则使用普通等待定时器。等待事件无需持续轮询,后者会占用内核。系统定时器的全局分辨率不会因此改变。

对于每个信号,都会记录计划期限、生成器唤醒、实际信号、接收方唤醒、模拟、命令发送、GPU 时间戳和显示事件。共同的帧标识符将所有阶段关联起来。

计划期限 → 生成器唤醒 → 信号
↓
接收方唤醒
↓
CPU → 命令 → GPU
↓
Present → 输出事件

在这些时间线中,可以分别看到定时器延迟和接收方唤醒延迟。Core Latency 的起点是实际信号,因此从计划期限到信号的这一步在此指标中不计入。

结果包含所测路径 latency_path 的分阶段拆解——分别针对 Baseline 和 Loaded。各阶段从实际信号开始计算:

阶段 测量内容
signal_to_consumer_wake 从信号到接收方唤醒
cpu_processing CPU 处理:模拟和帧数据准备
cpu_end_to_submit_start 从 CPU 工作结束到开始准备发送之间的暂停
workload_submit_cpu_span 图形 API 命令的准备和写入
submit_start_to_gpu_begin 从准备开始到 GPU 工作开始;这不是纯粹的队列延迟
gpu_execution GPU 工作本身的执行,以 GPU 周期计
presentation spans 显示:Present 的包装以及从信号和从 GPU 工作结束到 ScreenTime 的间隔

每个阶段都以包含统计量和百分位数的分布给出。各段按每一对标记分别计算,而不是用两个中位数相减。如果阶段的终点标记缺失或不可靠,其分布保持为空——没有替代值。定时器延迟(计划期限与实际信号的偏差)作为信号前的单独诊断记录,不计入路径的总值。

CPU 时间通过 QueryPerformanceCounter 记录。对于 GPU,引擎在测量的工作周围放置两个 timestamp query,通过 GetTimestampFrequency 获取队列频率,并将周期差转换为毫秒:

GPU work, ms = (GPU_end − GPU_begin) × 1000 / GPU_frequency

根据 Microsoft 关于 D3D12 timing 的文档,timestamp query 反映工作通过管线到达末端的过程,而 GPU 和 CPU 计数器通过 GetClockCalibration 关联起来。

GPU/QPC 校准对允许在与信号相同的时间轴上表示 GPU 工作的完成:

GPU_completion_QPC = calibration_QPC +
(GPU_end − calibration_GPU) × QPC_frequency / GPU_frequency
Core Latency, ms =
(GPU_completion_QPC − signal_QPC) × 1000 / QPC_frequency

此估计的精度在很大程度上取决于 CPU 和 GPU 时钟的匹配精度。它仍然不覆盖鼠标的 USB 路径、矩阵扫描时间或像素响应。Microsoft 单独描述了高精度 QPC 标记的细节。

Baseline 在此负载的最小配置下测量延迟。Loaded 使用校准到 8,333333 毫秒的 GPU 负载,即大约 120 Hz 的计算预算。物理显示器可能具有不同的刷新率。

校准在 1-4096 的范围内改变着色器内部的复杂度。通道数保持固定:四个后处理通道。首先围绕目标时间选择范围,然后对其进行细化并验证所选配置。要在快速显卡上占用相同的时间,需要更复杂的工作。

在性能测试中,工作量是固定的。在 Loaded Latency 中,负载经过校准,使 GPU 工作时间在不同显卡上接近。测量后获得的时间标记不会进行归一化。

延迟测试的帧输出通过单独的呈现路径进行:flip-discard 模式下的无边框窗口、最大帧延迟(maximum frame latency)1、DXGI 等待对象以及撕裂(如果系统支持)。此路径与固定的性能负载分离,后者在屏幕缓冲区之外执行,不会引起 Present。

对于显示事件,使用 PresentMon 2.5.1 库。这是一个 Windows 中图形事件分析的 ETW 项目,由其作者描述。在此测量管线中不使用 Procmon / Process Monitor。

PCBenchmarkX 启动自己的收集会话,筛选自己进程的事件,并将帧与软件信号关联起来。这不需要单独的服务和手动启动单独的 PresentMon。

保存额外的间隔:

  • 从信号到 Present;
  • 从 Present 到 ScreenTime;
  • 从信号到 ScreenTime。

ScreenTime 是帧显示的软件事件;不使用光电二极管测量屏幕发出的光。在 CPU/GPU/Latency 的基础模型中,Baseline 和 Loaded 的权重在延迟组件内为 20/80。显示指标不包含在 PC Score 中;包含哪些内容在分数计算中描述。启动 ETW 会话可能需要以管理员身份运行或成为“性能日志用户”组的成员。如果会话无法启动,则不会有此诊断块,并且失败会明确记录在结果中。缺少数据不等于零延迟。

PresentMon 的 GPU 时间也与自有 D3D12 时间分开存储。PresentMon 的开发者指出了 HAGS 下 GPU 指标精度的限制。因此,引擎不会用来自 ETW 的估计值替换自有 GPU timestamps。

在 PCBenchmarkX 中开发了信号生成器、帧阶段匹配、CPU 模拟、D3D12 负载、Loaded 校准、重复块的顺序、测量收集、统计处理和分数模型。QPC 和 D3D12 由 Windows 提供。对于通过 ETW 收集图形事件,使用开源项目 PresentMon。

测量描述已针对引擎 0.8.0 更新于 2026-10-02。Microsoft 关于 QPC 和 D3D12 的文档已在此日期重新检查。PresentMon 链接指向所使用的版本 2.5.1。