/ Performance,Windows / 64浏览

如何低成本的获取到应用卡顿情况

引入

在做 WPA 分析的时候,会通过 UI Delay 来判断应用卡顿的时间点。那我们是否可以单独把这一部分数据拎出来,来评估应用卡顿情况?

UI Delays 视图是依据什么来做的

WPA 大部分数据都是来源于众多 ETW Provider,也就是说,我们想获取到卡顿数据,就是找到特定的 provider 的特定事件。

通过对比 UI Delys 视图和 Generic Events 的视图。在 Generic Events 的视图中按 Process 排序,找到有出现卡顿的进程,分析其所有的事件。

于是可以看到,TaskName 为 MessageCheckDelayInputProcessDelay两个 keyword。

结论:

UI Delays 视图根据 Microsoft-Windows-Win32kMessageCheckDelayInputProcessDelay 两个事件来实现 UI 卡顿的可视化。

看看 Provider 里还有什么

由于我们已经找到了 Provider,并且也找到了两个事件。那是否还有其他事件呢?接下来到 Microsoft-Windows-Win32k 中去看看

我们可以在下面这个链接中看到 Microsoft-Windows-Win32k 的具体定义。

https://github.com/nasbench/EVTX-ETW-Resources/blob/7245ef4fa8c5be2ff75c58574f0c053322a10d52/ETWProvidersManifests/Windows11/24H2/W11_24H2_Pro_2024102_26100.1742/WEPExplorer/Microsoft-Windows-Win32k.xml#L1

找到 MessageCheckDelay

<Event>
                <Id>38</Id>
                <Version>0</Version>
                <Channel>Microsoft-Windows-Win32k/Tracing</Channel>
                <Level>Information</Level>
                <Task>MessageCheckDelay</Task>
                <Keyword>UIUnresponsiveness</Keyword>
                <Template><![CDATA[
<template xmlns="http://schemas.microsoft.com/win/2004/08/events">
  <data name="Flags" inType="win:UInt32" outType="win:HexInt32"/>
  <data name="DelayTimeMs" inType="win:UInt32" outType="xs:unsignedInt"/>
  <data name="TimeSinceInputRemoveMs" inType="win:UInt32" outType="xs:unsignedInt"/>
  <data name="TimeSinceOldestInputMs" inType="win:UInt32" outType="xs:unsignedInt"/>
  <data name="ClassName" inType="win:UnicodeString" outType="xs:string"/>
  <data name="TopLevelClassName" inType="win:UnicodeString" outType="xs:string"/>
  <data name="ImagePath" inType="win:UnicodeString" outType="xs:string"/>
  <data name="MessageId" inType="win:UInt32" outType="xs:unsignedInt"/>
  <data name="WParam" inType="win:UInt64" outType="xs:unsignedLong"/>
</template>
]]></Template>
            </Event>

还有 InputProcessDelay

<Event>
                <Id>37</Id>
                <Version>0</Version>
                <Channel>Microsoft-Windows-Win32k/Tracing</Channel>
                <Level>Information</Level>
                <Task>InputProcessDelay</Task>
                <Keyword>UIUnresponsiveness</Keyword>
                <Template><![CDATA[
<template xmlns="http://schemas.microsoft.com/win/2004/08/events">
  <data name="Flags" inType="win:UInt32" outType="win:HexInt32"/>
  <data name="TimeSinceInputRemoveMs" inType="win:UInt32" outType="xs:unsignedInt"/>
  <data name="TimeSinceOldestInputMs" inType="win:UInt32" outType="xs:unsignedInt"/>
  <data name="ClassName" inType="win:UnicodeString" outType="xs:string"/>
  <data name="TopLevelClassName" inType="win:UnicodeString" outType="xs:string"/>
  <data name="ImagePath" inType="win:UnicodeString" outType="xs:string"/>
  <data name="MessageId" inType="win:UInt32" outType="xs:unsignedInt"/>
  <data name="WParam" inType="win:UInt64" outType="xs:unsignedLong"/>
</template>
]]></Template>
            </Event>

可以看到,他们的关键词(keyword)都是 UIUnresponsiveness,于是我们可以看看这个关键词下的所有事件。汇总如下:

EventIDTask事件含义事件备注
35WaitCursor表示系统或应用程序显示了等待光标(忙碌指示)可能用于追踪界面响应延迟或繁忙状态下的性能问题
37InputProcessDelay表示输入(如鼠标、键盘等)无法及时被处理,出现延迟用于检测应用程序或系统在处理输入消息时是否出现卡顿或无响应
38MessageCheckDelay表示在检查或处理窗口消息时出现延迟用于衡量窗口消息循环中出现的滞后,监控UI或系统性能
160SmoothRotation (Start)表示开始进行平滑旋转(如屏幕方向切换),启动事件主要用于追踪自动旋转(AutoRotation)启动,记录屏幕方向变化及其来源
161SmoothRotation (Stop)表示结束平滑旋转,停止事件主要用于追踪自动旋转结束,衡量旋转过程的时长或效果
205ForegroundWindowFullScreen (Start)表示前台窗口进入全屏状态,开始事件用于监控当前前台应用是否切换至全屏,以便进行性能或模式切换追踪
206ForegroundWindowFullScreen (Stop)表示前台窗口退出全屏状态,停止事件用于监控当前前台应用退出全屏模式,方便进行状态切换或性能追踪

怎么做

根据可以获取到的事件。我们可以订阅 ETW 事件,当事件发生时,则证明应用发生卡顿。

怎么实时订阅可以看:如何通过 C++ 实时监听 ETW 事件

Windows是如何区分互联网下载文件和本地文件的
Windows是如何区分互联网下载文件和本地文件的
【译】ETW 堆跟踪 – 每个分配都被记录
【译】ETW 堆跟踪 – 每个分配都被记录
【译】Wait Analysis – 寻找空闲时间
【译】Wait Analysis – 寻找空闲时间
如何通过 ETW Provider 来记录应用日志
如何通过 ETW Provider 来记录应用日志
如何通过 C++ 实时监听 ETW 事件
如何通过 C++ 实时监听 ETW 事件
【译】调查并确定 Windows 运行速度变慢问题
【译】调查并确定 Windows 运行速度变慢问题

0

  1. This post has no comment yet

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注