ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

microsoft-ui-xaml perf/tooling 实战:XamlTimeline 共享核心与 WinUI 3 启动 ETW 遥测分析工具链

microsoft-ui-xaml perf/tooling 实战:XamlTimeline 共享核心与 WinUI 3 启动 ETW 遥测分析工具链 microsoft-ui-xaml perf/tooling 实战XamlTimeline 共享核心与 WinUI 3 启动 ETW 遥测分析工具链【免费下载链接】microsoft-ui-xamlWinUI: a modern UI framework with a rich set of controls and styles to build dynamic and high-performing Windows applications.项目地址: https://gitcode.com/GitHub_Trending/mi/microsoft-ui-xaml本文基于 microsoft-ui-xaml 仓库的perf/tooling/模块讲解一套用于分析 WinUI 3 / Windows App SDK 应用启动 ETW.etl跟踪数据的工具链共享核心库 XamlTimeline、WinUI 3 桌面查看器与 WPA 插件两个前端以及数据驱动的区域定义文件。读完本文你可以自行构建并运行这套工具定位应用从UserClick到App ready to interact每一阶段的耗时并通过修改区域定义 XML 扩展自己的启动阶段判定规则。1. 工具链全景一个核心库两个前端perf/tooling下的工具专门用于分析WinUI 3 / Windows App SDK 应用启动的 ETW 跟踪文件.etl。三个项目共享同一个核心库结构如下项目目录目标框架定位XamlTimelineperf/tooling/XamlTimeline/netstandard2.0类库共享核心—— 事件模型、区域解析、Track 1 时间线检测算法被两个前端复用。无 UI、零外部 NuGet 依赖XamlTelemetryViewerWInui3perf/tooling/XamlTelemtryViewerWInui3/net8.0-windowsWinUI 3 应用独立桌面查看器 —— 可并排加载多个.etl跟踪选项卡式事件网格 堆叠时间线泳道支持过滤、缩放多轨道时间线、亮/暗主题切换AppBootingVisualizerPluginperf/tooling/AppBootingVisualizerPlugin/netstandard2.0WPA 插件.ptixWindows Performance Analyzer 插件 —— 在 WPA 内以 3 轨道 Gantt 图渲染同一套启动区域与事件配对--------------------------- | XamlTimeline | netstandard2.0, no external deps | TelemetryEvent | | PhaseDefinition / EventMatcher | TimelineItem / PayloadFilter | RegionsLoader ( embedded XamlAppLaunch.regions.xml) | TimelineBuilder (Track 1 detection) --------------------------- ^ ^ ProjectReference ProjectReference | | ------------------- ------------------------------ | XamlTelemetryViewer | | AppBootingVisualizerPlugin | | WInui3 (WinUI app) | | (WPA .ptix plugin) | --------------------- ------------------------------三个项目位于同一个解决方案 Tooling.sln 中统一打开、统一构建。1.1 为什么需要一个共享库两个前端历史上各自维护了一份重复的事件模型与配对逻辑。真正完全一致的部分被抽取到了XamlTimeline包括TelemetryEvent—— 一条规范化后的跟踪事件此前分别是查看器的TelemetryEvent与插件的BootEventTimelineTrack、RegionKind、PayloadFilter、EventMatcher、PhaseDefinition、TimelineItem—— 区域与时间线模型RegionsLoader—— 解析WPA Regions of Interest格式文件工具元数据放在标准Metadata节点中携带 track/kind/颜色等信息并通过LoadEmbeddedDefault()暴露内嵌在库中的规范XamlAppLaunch.regions.xml。两个应用加载的是同一份区域定义TimelineBuilder.BuildTrackOne(...)—— Track 1 的 marker/phase 检测算法XAML 终点启发式、${ProcessName}负载匹配等。XamlTimeline 选择netstandard2.0作为目标框架原因是它是两个消费方的最大公约数——net8.0-windows的 WinUI 应用和netstandard2.0的 WPA 插件都能引用它。从 XamlTimeline.csproj 可以看到工程约束写得很明确TargetFrameworknetstandard2.0/TargetFramework、LangVersionlatest/LangVersion、Nullableenable/Nullable零外部包依赖因此不会给插件的.ptix增加任何 DLL现代 C# 特性record、init、可空注解通过 LangVersion 加上Polyfills/IsExternalInit.cs这个小 polyfill 启用XamlAppLaunch.regions.xml以EmbeddedResource内嵌进程序集见第 4 节。关于Directory.Build.props/.targets的重要提醒XamlTimeline 自带了一对近乎空白的Directory.Build.props/.targets它们刻意不向仓库根目录链式继承。这样做是为了把它隔离在仓库根级、按构建风味build flavor区分obj目录重定向的机制之外使其始终还原到单一、稳定的obj/project.assets.json保证 Visual Studio 能定位到它。请勿删除这两个文件参见 Directory.Build.props。2. XamlTimeline 核心模型从 ETL 事件到时间线条目共享库的六个核心类型构成了「原始事件 → 匹配 → 时间线条目」的完整数据通路类型文件职责TelemetryEventTelemetryEvent.cs一条规范化跟踪事件时间戳、进程名/PID/TID、Provider 名 Provider GUID、事件名/ID、Opcode、Level以及解析后的负载字段字典Fields大小写不敏感查找PhaseDefinitionPhaseDefinition.cs从区域 XML 加载的静态区域描述名称、颜色、Track、Kind、Start/Stop 匹配器、SpecialProviders、ThresholdPercentage默认 5.0、ProcessDependentEventMatcherEventMatcher.cs按Provider GUID主键 可选事件 ID/名称匹配事件附带可选负载字段过滤器其中${ProcessName}占位符在求值时替换为候选进程的镜像名PayloadFilterPayloadFilter.cs单个负载字段过滤器(Field, Value)Value可含${ProcessName}占位符TimelineItemTimelineItem.cs在跟踪中具体检测到的区域实例Marker只有 Start或 PhaseStart End并携带所属进程名/PIDDuration由两端时间戳差值导出TimelineTrack/RegionKindTimelineEnums.csTrace 1全跟踪时间线shell/内核/应用间的生命周期与Process 2进程作用域时间线Marker时点与Phase时长两个值得注意的设计细节Provider GUID 是匹配主键。EventMatcher.cs 中Matches(ev)先比对ProviderGuid事件名用的是大小写不敏感的子串包含判断IndexOf ... OrdinalIgnoreCase而非全等——这是因为 Provider 友好名在不同跟踪间可能变化而 GUID 稳定。负载匹配跳过下划线。EventMatcher.cs 的ContainsIgnoringChars在比较负载值与区域过滤值时会把双方字符串中的_全部剔除后再做小写子串匹配。源码注释给出了原因ETW 负载里应用 ID 的写法不一定和镜像名一致例如镜像是BlankWinuiApp而负载是appIdblank_winui_app跳过分隔符_才能可靠匹配。3. 区域定义文件XamlAppLaunch.regions.xml整套工具的时间线没有任何关于 XAML 或 WinUI 的硬编码——所有启动阶段都来自一个数据文件XamlAppLaunch.regions.xml内嵌在共享库中两个前端通过RegionsLoader.LoadEmbeddedDefault()加载同一份内容。它是标准的WPA Regions of Interest文件InstrumentationManifest/Instrumentation/Regions/RegionRoot/Region信封因此可以直接在 WPA 中通过Trace Trace Properties Add打开WPA 不认的工具元数据则放在标准Metadata节点里WPA 处理时会忽略它、仅在 UI 中展示为列。3.1 XML 模式与元数据字段InstrumentationManifest InstrumentationRegions RegionRoot Guid{...} NameXamlAppLaunch FriendlyNameXAML App Launch Region Guid{...} NameXamlAppLaunch-MyPhase FriendlyName... Start Event Provider{guid} IdN Version0 NameEventName / PayloadIdentifier FieldNameappId FieldValue${ProcessName} / !-- 可选 -- /Start Stop !-- 仅 Phase -- Event Provider{guid} NameEventName / PayloadIdentifier FieldNameImageName FieldValue${ProcessName} / /Stop Metadata Track1/Track KindMarker|Phase/Kind Color#RRGGBB/Color ProcessDependenttrue|false/ProcessDependent SpecialProvidersProviderA;ProviderB/SpecialProviders /Metadata /Region /RegionRoot /Regions/Instrumentation /InstrumentationManifestMetadata中被 RegionsLoader 读取的字段字段含义默认值Track1 全跟踪时间线跨进程生命周期2 进程时间线进程内阶段1KindMarker单个 Start 事件时点或PhaseStart..Stop 时长MarkerColor时间线视图 / Gantt 图色块#607D8BProcessDependent区域是否只对选中的 PID 求值falseSpecialProviders分号分隔的 Provider 白名单驱动 Track 2 子视图空ThresholdPercentageTrack 2 子项可见性阈值5.0XamlEndHeuristicStop 端点用「XAML 终点启发式」选取见第 4 节falseProcessDependentEndStop 事件必须来自选中进程false解析规则可从 RegionsLoader.cs 的ParseRegion验证根元素必须是InstrumentationManifestName唯一 ID与FriendlyName显示标签至少有一个KindPhase却缺少Stop会直接抛出InvalidDataExceptionPayloadIdentifier FieldName FieldValue会被折叠进对应端点的EventMatcher。${ProcessName}是这份 XML 能对任意进程通用化的关键求值时它被替换为候选进程镜像名先剥掉尾部.exe和首部ms前缀见 TimelineBuilder.cs 的ExtractProcessNameToken再做大小写不敏感的 contains 匹配。3.2 内置的 11 个启动区域当前文件定义了 11 个区域3 个 Marker 8 个 Phase完整覆盖打包版 WinUI 3 应用的启动生命周期区域类型起点事件终点事件UserClickMarkerMicrosoft.Windows.AppLifeCycle.UI的AppLaunch_UserClick负载appId匹配${ProcessName}—Pre-ProcessPhaseAppLaunch_UserClick内核Microsoft-Windows-Kernel-Process的ProcessStart负载ImageNameProcessStartMarker内核ProcessStart进程刚创建、仍处于挂起态—Packaged App InitPhaseProcessStartMicrosoft.Windows.ApplicationModel.DesktopAppx的AddProcessToHeliumContainersvchost AppInfo 阶段 Helium 容器Native Bring-upPhaseAddProcessToHeliumContainerMicrosoft.Windows.CoreApplication的AppCreation静态 DLL 加载、WART 初始化、WinUI3 二进制加载XAMLPhaseMicrosoft-Windows-XAML的InitializeCoreId31Frame但由XAML 终点启发式确定XamlEndHeuristictrueApp ready to interactMarker首帧合成提交AppLaunch事件—PreLaunch_To_ProcessStartPhasePreLaunch内核ProcessStartProcessStart_To_WinMainEntryPhase内核ProcessStartwWinMainEntryWinMainEntry_To_FirstFrameRenderPhasewWinMainEntryFirstRenderFirstFrameRender_To_ReadyToInteractPhaseFirstRenderFirstIdle文件头部注释列出了 6 个核心 Provider GUIDMicrosoft.Windows.AppLifeCycle.UI、Microsoft.Windows.ShellExecute、Microsoft.Windows.ApplicationModel.DesktopAppx、Microsoft-Windows-Kernel-Process、Microsoft.Windows.CoreApplication、Microsoft-Windows-XAML文件实际还引用了另外 3 个 GUID分别承载AppLaunchready-to-interact 标记、PreLaunch以及wWinMainEntry/FirstRender/FirstIdle这类原生启动打点事件。4. Track 1 检测算法源码解析Track 1全跟踪时间线的检测算法集中在 TimelineBuilder.cs是查看器与 WPA 插件共用的唯一检测实现。4.1 BuildTrackOne主流程BuildTrackOne(events, definitions, selectedProcessId, selectedProcessName)L26-L60的完整流程用ExtractProcessNameToken从进程镜像名生成可匹配 tokenMyApp.exe→MyAppmsfoo→foo遍历所有PhaseDefinition跳过 Track 2Process定义——那些由查看器在用户下钻时按需构建按Kind分派到DetectMarkers或DetectPhases命中的事件生成TimelineItem并打上所选进程名/PID 戳便于多进程调用方按进程分组结果按Start时间排序返回。4.2 Marker 与 Phase 的检测语义MarkerDetectMarkers扫描事件序列返回第一个匹配yield break。是否强制 PID 过滤由def.Track Process || def.ProcessDependent决定——Track 1 的 Marker 允许来自任意进程依赖${ProcessName}负载匹配来定位目标应用。PhaseDetectPhases是一个「pending start → stop」状态机。先等到Start匹配若ProcessDependentEnd为真Start 也须来自选中进程随后等待Stop匹配并配对输出。未配对的尾部 Start 被有意丢弃——没有确定终点的 phase 不输出避免时间线出现向右无限延伸的假阶段。注意 Track 1 的 Phase 默认不区分 PIDStart/Stop 事件可能来自不同进程例如 shell 侧的UserClick与内核侧的ProcessStart因此依赖负载过滤 时间先后配对。4.3 XAML 终点启发式15 帧配对XAML区域的 Stop 写的是Frame事件但直接用「第一个 Frame」做终点并不合理——XAML 从InitializeCore开始会经历大量帧活动。源码给出了启发式方案FindingHeuristicEndpointForXaml以 Stop 事件名Frame构造两个模式Frame/win:Start与Frame/win:Stop从 Start 事件索引之后扫描终点不可能早于起点把同名 Provider 的Frame/win:Start压栈遇到Frame/win:Stop时弹栈计为一对「同步帧」累计到第 15 对同步帧时返回该 Stop 事件作为 XAML 阶段终点若扫描结束仍未满 15 对退化为返回最后看到的 Stop一个都没有则返回 null该 Phase 视为不存在。从源码结构看这一启发式的意图是XAML 子系统稳定运行、持续渲染至少 15 帧之后才认为「XAML 生命周期」结束从而把初始化期与稳态渲染期区分开。该逻辑仅当区域 Metadata 中XamlEndHeuristictrue时启用当前配置中只有XAML区域使用。5. 两个前端的使用方式5.1 XamlTelemetryViewerWInui3独立 WinUI 3 查看器完整的特性与操作步骤见其 README核心用法摘要先捕获 ETL本工具只做分析不做捕获典型的打包版 WinUI 3 应用捕获方式wpr -start GeneralProfile -filemode :: 启动并操作你的应用 wpr -stop trace.etl查看器工作流启动应用后点击Select trace file…选择一个或多个.etl每个文件成为一个选项卡点击Load trace在工作线程解析返回按时间戳排序的TelemetryEvent列表与进程清单加载可取消重复点击 Load 会先取消上一次解析可选在Filters…窗口按「组 条件」组织过滤组内/组间分别And/Or支持ProcessName、ProviderName、EventName、Level、Opcode、Payload等字段与Contains/Equals/StartsWith/EndsWith运算符大小写不敏感也可直接写查询文本如ProviderName Contains XAML And Level Equals Informational并点击Parse Query Text点击 Timeline打开时间线窗口每个跟踪一条 Track 1 泳道各自可选进程默认选事件数最多的 XAML 进程点击 Track 1 阶段展开 Track 2该区域内按 Provider 的活动点击 Provider 再下钻 Track 3按事件的子轨道Ctrl 滚轮缩放、左键拖拽平移⬇ Download将 Track 1 条目导出为文本报告到 Downloads 目录。运行环境前提Windows 10 1809build 17763或更高推荐 Windows 11、.NET 8 SDK、Windows App SDK 2.1.3 运行时依赖包包括Microsoft.WindowsAppSDK2.1.3、Microsoft.Windows.EventTracing.Processing.All1.12.10、CommunityToolkit.Mvvm8.4.0 等详见其 README 的依赖表。5.2 AppBootingVisualizerPluginWPA 插件插件的完整文档见 AppBootingVisualizerPlugin/README.md它在 WPA 内把原始 ETL 渲染为 3 轨道 GanttTrack 1 — Launch Timeline每个进程一行可展开的 Gantt检测第 3 节所述的启动区域显示窗口自动收缩到[首个区域起点 … 末个区域终点]避免图表被启动前后的空白时间稀释进程列作为 pivot keyWPA 按进程分组折叠Track 2 — Events by Provider把同一(EventName, ThreadId)上的 ETWOpcode1/Opcode2配对渲染为带真实时长的 Gantt 条按 Provider → Process → EventName pivot每个 Track 1 区域注册一个TableConfiguration预设自动过滤到该区域的SpecialProviders与 Track 1 共享 x 轴在 Track 1 上拖选时间范围会自动约束 Track 2Track 3 — All EventsTrack 1 窗口内所有原始事件渲染为点标记Start End兜住 Track 2 丢弃的Opcode0信息事件与未配对的 Start/Stop。插件特有的性能优化在MultiProcessTrackOneBuilder它把所有候选 PID 的 Track 1 在一次扫描中构建完成ProcessDependent区域按 PID 分桶后委托给共享的TimelineBuilder.BuildTrackOne其余区域做全跟踪级匹配 逐进程${ProcessName}负载路由将成本从 O(进程数 × 事件数 × 区域数) 降到约 O(事件数 × 区域数)。安装步骤仓库遵循 source-only 策略不提交预编译.ptix构建.ptix见第 6 节得到AppBootingVisualizerPlugin-version.ptix约 19 MBWPA →Manage → Plugins → Install Plugin…选择该文件重启 WPAFile → Open打开.etl跟踪三张表出现在 Graph Explorer 的App Booting Visualizer Plugin分类下。开发热加载替代方案dotnet publish -o PluginPackage后用wpa.exe -addsearchdir PluginPackage 完整路径启动 WPA直接加载插件 DLL 而无需安装.ptix。6. 构建与部署操作三个项目共用 Tooling.sln。在Visual Studio中打开该解决方案WinUI 查看器是默认启动项目已启用 Deploy选择平台x64按F5即可构建、部署 MSIX 包并启动。请打开.sln而非裸.csproj这样XamlTimeline的项目引用才能在新克隆上正确解析。6.1 命令行构建 WinUI 查看器cd perf\tooling dotnet build .\Tooling.sln -p:Platformx646.2 构建 WPA 插件.ptixcd perf\tooling\AppBootingVisualizerPlugin\AppBootingVisualizerPlugin .\Pack.ps1 # - AppBootingVisualizerPlugin-version.ptix .\Pack.ps1 -Configuration Release # Release 构建Pack.ps1内部执行三步dotnet publishXamlTimeline.dll会被自动打包进产物→ 镜像到暂存目录并剥离Microsoft.Performance.SDK*.dll、*.pdb与pluginManifest.json若打包了 SDK 运行时plugintool会静默失败提示 SDK should not present因为 WPA 加载自己的副本→plugintool pack生成最终.ptix。版本号当前为 1.0.0取自 pluginManifest.json 的identity节。前置工具需安装固定的预览版dotnet tool install --global Microsoft.Performance.Toolkit.Plugins.Cli --version 0.1.77-preview该包在 nuget.org 上只有 preview 版本必须显式--version。6.3 单独构建共享库cd perf\tooling\XamlTimeline dotnet build .\XamlTimeline.csproj7. 修改区域定义数据驱动的扩展点启动区域完全由一个文件数据驱动XamlTimeline/Regions/XamlAppLaunch.regions.xml内嵌于共享库。编辑它同时改变查看器与 WPA 插件的显示——任何改动后需要重新构建dotnet build/dotnet publish/Pack.ps1。一个最小可粘贴的 Phase 示例结构需满足第 3.1 节的信封与校验规则且KindPhase必须提供StopRegion Guid{...} NameXamlAppLaunch-MyPhase FriendlyNameMyPhase Start Event Provider{531a35ab-63ce-4bcf-aa98-f88c7a89e455} Id31 Version0 NameInitializeCore / /Start Stop Event Provider{531a35ab-63ce-4bcf-aa98-f88c7a89e455} NameFrame / /Stop Metadata Track1/Track KindPhase/Kind Color#56B4E9/Color ProcessDependenttrue/ProcessDependent XamlEndHeuristictrue/XamlEndHeuristic SpecialProvidersMicrosoft-Windows-XAML/SpecialProviders /Metadata /Region实践要点Guid为 WPA 必需属性且应唯一Name是唯一 IDFriendlyName是工具显示标签${ProcessName}只能出现在PayloadIdentifier的FieldValue中运行时被替换为所选进程镜像名剥.exe、剥ms前缀后 contains 匹配想让区域只跟踪所选进程置ProcessDependenttrue/ProcessDependent若仅 Stop 端要求进程归属用ProcessDependentEndtrue/ProcessDependentEnd如Native Bring-up区域;SpecialProviders决定该区域在 Track 2 中的 Provider 白名单ThresholdPercentage控制 Track 2 子项的可见性阈值由于该文件同时是标准 WPA Regions of Interest 文件它也能独立于本工具链直接在 WPA 中加载使用。8. 小结perf/tooling用「一个netstandard2.0零依赖共享库 两个前端」的架构把 WinUI 3 启动遥测分析中的事件模型、区域解析和 Track 1 检测算法收敛为单一实现保证了 WinUI 查看器与 WPA 插件对同一跟踪产生一致的数值而把启动阶段判定外置为可编辑的XamlAppLaunch.regions.xml使得新增阶段、调整配色或扩展 Provider 白名单都不需要改动 C# 代码。如果你在做 WinUI 3 / Windows App SDK 应用的启动性能工作这套工具链提供的是从wpr捕获的原始 ETL 到分阶段 Gantt 耗时视图的完整通路。【免费下载链接】microsoft-ui-xamlWinUI: a modern UI framework with a rich set of controls and styles to build dynamic and high-performing Windows applications.项目地址: https://gitcode.com/GitHub_Trending/mi/microsoft-ui-xaml创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表