【问题标题】:Speeding up compilation in UWP?在 UWP 中加速编译?
【发布时间】:2019-03-25 22:09:06
【问题描述】:

在 WPF 工作了很长时间后,我正在研究 UWP,编译速度非常慢。

我理解为什么发布编译很慢(网络原生编译),但在调试中禁用了它,但在 F5 和屏幕上显示的应用程序之间仍然需要很长时间,即使对于空白应用程序也是如此。

有什么方法可以加快速度(即使以运行时性能为代价)?当您习惯使用 C# 时,它真的很难使用,因为它可以为您提供极快的编译时间并在每次小的更改后进行测试。

例如,只需右键单击并在一个非常简单的(4 页,每行

按照建议,您可以在此处找到下载的最小示例: https://www.dropbox.com/s/0h89qsz66erba3x/WPFUWPCompileSpeed.zip?dl=0

这只是一个空白 wpf 和空白 uwp 应用程序的解决方案。 WPF 的编译时间刚刚超过 1 秒,UWP 为 12 秒,在每种情况下都清理了解决方案,并且我正在测试的单个项目被右键单击并重建。这是在调试中(没有 .net Native 编译)

【问题讨论】:

  • 您的病毒检查器是否扫描 VS 安装文件夹?我发现这会在编译过程中导致显着减速。我告诉 AV 排除这些文件夹,编译速度显着提高。
  • @AvrohomYisroel 除了 Windows Defender 之外,我没有使用任何其他安全软件,但是为了确保我禁用了它并且没有显着差异(仍然 ~= 1 sec WPF,~= 12sec UWP,同一解决方案中的两个空白应用程序)
  • 哦,听起来像是 UWP 的东西。抱歉,由于我不使用 UWP,因此无法提供进一步帮助。不要忘记,如果您在其他地方找到答案,请务必在此处发布,以便其他人受益。
  • @IllidanS4 这与我的问题完全无关
  • 你说的是编译时间还是你可以在屏幕上看到应用程序的时间?您的部署目标是什么(本地机器或模拟器)?也许编译很快,但部署很慢(安装了 UWP 应用,而不是像 WPF 那样简单地执行)。

标签: c# .net visual-studio uwp


【解决方案1】:

我绝对同意 UWP 编译比 WPF 慢得多。每当我达到大约 5-6 打 xaml 窗口或视图时,我总是不得不拆分我的 WPF 程序集,以便将增量编译时间保持在 10-20 秒。事情看起来的方式,我的 UWP 程序集可能会增长到只有大约 2 或 3 打项目,然后才需要太长时间来编译。当您尝试进行迭代编码和调试时,任何编译时间超过 10 秒的程序集都会出现问题。

如果您还没有尝试过,这里有两个建议。首先要做的是转到构建选项卡并始终记住取消选中“使用 .NET 本机工具链编译”。这对于正常的调试/测试迭代毫无用处。

接下来要做的是使用 procmon 监控您的构建操作。这将显示您的工作站可能特有的任何问题(如病毒扫描、其他可能干扰的应用程序)。

以下是我注意到与 WPF 相比会减慢 UWP 编译速度的因素:

  • 大量编译过程(在构建输出窗口中查看):
> 标记编译过程1: > Xaml 预编译: > MarkupCompilePass2: > GenerateTargetFrameworkMonikerAttribute: > 核心编译: > CopyGeneratedXaml: > 复制文件到输出目录: > ComputeProcessXaml 文件: > CustomOutputGroupForPackaging: > 获取包装输出: > _GenerateProjectPriConfigurationFiles: > _GenerateProjectPriFileCore:
  • Core/Nuget 依赖项

与 .Net Framework 不同,您对 UWP 的所有依赖项都来自 .Net core 和 nuget。您应该能够使用 procmon 并查看对 VS 保存这些内容的目录的大量读取:C:\Program Files (x86)\Microsoft SDKs\UWPNuGetPackages。请注意,依赖项本身的质量与 .Net 框架依赖项(在 WPF 中)没有完全不同的质量。但是在如何收集这些依赖项以及如何在编译操作期间将它们推送到您的输出目录中(最终在最终的 Appx 目录中结束)方面存在很大差异。

  • 没有用于优化的“共享输出目录”。

使用 WPF,我们可以将类库目标单独发送到共享输出目录(通过检查它们的构建,同时取消检查其他库和应用程序 exe 本身)。然后我们可以启动调试器,而无需编译一大堆不一定会改变的东西。但是,UWP 要求我们构建入门级应用程序,无论我们是否尝试配置共享输出目录。

  • UWP 中需要新的“部署”步骤

WPF 没有每次构建 UWP 应用时都需要的新“部署”步骤。您将在构建配置中看到该复选框,它适用于入门级应用程序。如果不部署,调试时将看不到所有更改。

  • UWP 仍在积极变化中(与 WPF 不同)

他们不断改变 UWP 编译操作。很快我们将开始看到一个名为“WinUI”的库,它将引入另一个来自 NuGet 的 UWP 应用程序依赖项。这可能无助于编译性能方面的问题。

我认为一旦变化的步伐开始放缓,微软可能会决定专注于寻找提高编译性能的方法。在阅读 procmon 输出时,似乎很清楚 devenv.exe 完成的工作中只有不到一半是为我完成的。剩下的就是引入所有依赖项,以便我的代码可以针对它进行编译。必须有一种方法来优化这种重复处理。

【讨论】:

  • 感谢您提供如此详尽的回答,请问您在哪里找到记录的构建步骤(或者您是否自己深入研究了构建过程?)。我已经跳过 .net 原生管道进行调试,但我想了解整个管道是如何构建的,并检查每个组件以找出哪个组件慢,是否值得进行自定义编译?我已经授予您赏金,因为您的答案是完美的,并且清楚地验证了我的问题并回答了我的问题,但是如果您能详细说明您是如何解决这个问题的以及如何手动复制管道,那就太好了。无论如何,非常感谢
  • 感谢您的赏金。这是第一次。如果您将 MSBuild 项目输出详细程度设置为正常(或更高),则编译过程将在输出窗口中列出。它还在末尾列出了每个项目的总构建时间(“已用时间”)。
  • 如果您想了解更多关于您的构建的信息,您可以更改详细程度。但我总是发现使用 procmon 更有帮助,因为它列出了所有文件 I/O(有时甚至是很多网络或注册表活动)。关于这一点,另一个明显的性能建议是告诉 nuget 包管理器在构建期间不要下载东西。
  • 我不完全理解由于通过 UWP 应用程序引入的“核心/Nuget 依赖项”而产生的性能影响。我的 WPF 项目也引入了 nuget 依赖项,但与 UWP 应用程序的程度不同。我知道,如果您观看 procmon,您会看到文件 i/o,其中列出了您听说过的几乎所有程序集等等。但是使用 WPF,您可以有选择性地依赖单个程序集而不是臃肿的 nuget 包。
【解决方案2】:

Ronan (12 秒?)空项目的编译时间似乎有点高……我的通常运行时间不到 5 秒(空时)。

您可能想看看 CPU 发生了什么。单个项目的编译应该完全受 cpu 限制,尤其是在第二次或第三次尝试时,在文件系统缓存了您的源代码之后(并且下载了所有 nuget 依赖项)。您可能需要密切关注任务管理器并确保您在单核上全速运行(即,如果您有四个核心,则为 25%,八核为 12%,等等)。如果您看到 CPU 下降得太远,那么就出了问题。还要确保检查 CPU 是否被您所期望的常见事物使用,例如 devenv.exe、VBCSCompiler.exe 和 MSBuild.exe。

对于那些声称编译 UWP 项目的速度比其他人快得多的人来说,听听他们对 windows 社区工具包的基准测试可能会很有趣。 (https://github.com/windows-toolkit/WindowsCommunityToolkit/tree/rel/5.0.0) 最有趣的编译时间是针对 xaml 最重的项目。这是我的时间:

  • Microsoft.Toolkit.Uwp.UI.Controls 10 秒
  • 8 秒 Microsoft.Toolkit.Uwp.UI.Controls.Graph
  • 8 秒 Microsoft.Toolkit.Uwp.UI.Controls.DataGrid

基本的 Van Arsdel 库存应用程序是另一个要进行基准测试的东西。 https://github.com/Microsoft/InventorySample这是我的结果:

  • Inventory.App 需要 14 秒

VanArsdel 示例应用程序将是另一个很好的基准测试应用程序。 (注意这一点;您可能必须使用 Windows 内部版本,它可能会像我的那样搞乱您的 VS)。网址在这里:https://github.com/microsoft/vanarsdel 这是我的结果:

  • VanArsdel 项目需要 13 秒

请记住,大量面向 xaml 的项目通常也是最慢的,因为它们在各种编译过程中涉及更多的处理工作。

使用诊断输出

虽然构建项目所用的总时间很关键,但了解时间的来源也可能会有所帮助。如果您转到 Tools->Options->Build-and-Run,然后将项目构建输出详细程度设置为 Diagnostic,您可以获得一个摘要。然后编译有问题的项目。最后,您将看到如下所示的任务绩效摘要。请注意,CompileXaml 应该花费最多的时间。这五个项目似乎很常见。

任务绩效总结:

  100 ms  ValidateAppxManifest                       1 calls
  400 ms  ExpandPriContent                           1 calls
  400 ms  Csc                                        2 calls
  600 ms  ResolveAssemblyReference                   1 calls
 7000 ms  CompileXaml                                2 calls

如果您在每次编译时看到其他任何内容(例如 GenerateAppxManifest)都占用了几秒钟,那么这可能是您项目中的损坏问题。您应该能够通过搜索“完全”一词进行故障排除,如“完全构建目标 _GenerateCurrentProjectAppxManifest”。当你发现它时,它应该会告诉你它为什么要做额外的工作。

最低版本定位

我注意到,更改目标选项卡上的最低版本将使我的“CompileXaml”时间缩短三秒。

请参阅下文,将最低版本更改为 15063 有助于减少编译时间。我怀疑这与相关依赖项中的膨胀有关。

15063 (creators update) [4 seconds]
16299 (fall creators) [7 seconds]
17134 (version 1803) [ 7.5 seconds]

它并不总是针对创建者更新的选项,因此这可能不是通用修复。但有趣的是了解获得更新的 Windows 10 SDK 的影响。

【讨论】:

  • 我最近打开了一个支持案例,以了解为什么更改最小版本目标会增加 xaml 编译时间。微软能够承认他们意识到了这个问题。这是他们对 Visual Studio 开发者社区的回复的链接:developercommunity.visualstudio.com/content/problem/376045/…
  • “我们已经意识到这个问题,我们将在未来的 Windows SDK 版本中解决这个问题。您发现的这个性能问题是为了解决构建一致性问题而引入的,尤其是在增量编译器情况。考虑到这一点,我们正在寻找方法来改善这种情况,从而减少对编译时间的影响。”
猜你喜欢
  • 2014-04-03
  • 1970-01-01
  • 2013-03-17
  • 2017-06-19
  • 1970-01-01
  • 2018-04-10
  • 2013-10-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多