引入
在做 WPA 分析的时候,会通过 UI Delay 来判断应用卡顿的时间点。那我们是否可以单独把这一部分数据拎出来,来评估应用卡顿情况?
UI Delays 视图是依据什么来做的
WPA 大部分数据都是来源于众多 ETW Provider,也就是说,我们想获取到卡顿数据,就是找到特定的 provider 的特定事件。
通过对比 UI Delys 视图和 Generic Events 的视图。在 Generic Events 的视图中按 Process 排序,找到有出现卡顿的进程,分析其所有的事件。

于是可以看到,TaskName 为 MessageCheckDelay
和 InputProcessDelay
两个 keyword。
结论:
UI Delays 视图根据 Microsoft-Windows-Win32k
的 MessageCheckDelay
和 InputProcessDelay
两个事件来实现 UI 卡顿的可视化。
看看 Provider 里还有什么
由于我们已经找到了 Provider,并且也找到了两个事件。那是否还有其他事件呢?接下来到 Microsoft-Windows-Win32k
中去看看
我们可以在下面这个链接中看到 Microsoft-Windows-Win32k
的具体定义。
找到 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
,于是我们可以看看这个关键词下的所有事件。汇总如下:
EventID | Task | 事件含义 | 事件备注 |
35 | WaitCursor | 表示系统或应用程序显示了等待光标(忙碌指示) | 可能用于追踪界面响应延迟或繁忙状态下的性能问题 |
37 | InputProcessDelay | 表示输入(如鼠标、键盘等)无法及时被处理,出现延迟 | 用于检测应用程序或系统在处理输入消息时是否出现卡顿或无响应 |
38 | MessageCheckDelay | 表示在检查或处理窗口消息时出现延迟 | 用于衡量窗口消息循环中出现的滞后,监控UI或系统性能 |
160 | SmoothRotation (Start) | 表示开始进行平滑旋转(如屏幕方向切换),启动事件 | 主要用于追踪自动旋转(AutoRotation)启动,记录屏幕方向变化及其来源 |
161 | SmoothRotation (Stop) | 表示结束平滑旋转,停止事件 | 主要用于追踪自动旋转结束,衡量旋转过程的时长或效果 |
205 | ForegroundWindowFullScreen (Start) | 表示前台窗口进入全屏状态,开始事件 | 用于监控当前前台应用是否切换至全屏,以便进行性能或模式切换追踪 |
206 | ForegroundWindowFullScreen (Stop) | 表示前台窗口退出全屏状态,停止事件 | 用于监控当前前台应用退出全屏模式,方便进行状态切换或性能追踪 |
怎么做
根据可以获取到的事件。我们可以订阅 ETW 事件,当事件发生时,则证明应用发生卡顿。
怎么实时订阅可以看:如何通过 C++ 实时监听 ETW 事件
0