代码之家  ›  专栏  ›  技术社区  ›  Ronan Thibaudau

在UWP中加速编译?

  •  1
  • Ronan Thibaudau  · 技术社区  · 7 年前

    我在wpf工作了很长一段时间后就开始使用uwp,编译速度非常慢。

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

    有没有任何方法可以加快速度(即使以运行时性能为代价)?当你习惯于C给你极快的编译时间和每一次小的修改后的测试时,你真的很难处理。

    例如,只需在一个非常简单的(4页,每个<200行XAML,以及几乎0 C)上单击鼠标右键并重新生成,UWP项目在没有项目引用的情况下进行调试(没有.NET本机)几乎需要20秒。同时,一个更大的WPF应用程序(几十个窗口,数千行代码)需要几秒钟的时间,而且大部分时间都在复制子项目!

    正如建议的那样,您可以在这里找到一个下载的最小示例: https://www.dropbox.com/s/0h89qsz66erba3x/WPFUWPCompileSpeed.zip?dl=0

    这只是一个带有空白wpf&blank uwp应用程序的解决方案。wpf的编译时间仅超过1秒,对于uwp 12秒,在每种情况下解决方案都被清除,我测试的单个项目被右键单击并重新构建。这是在调试中(没有.NET本机编译)

    2 回复  |  直到 7 年前
        1
  •  1
  •   David Beavon    7 年前

    我完全同意UWP编译比WPF慢得多。每当我达到大约5到6打XAML窗口或视图时,我总是必须分解WPF程序集,以便将增量编译时间缩短到10到20秒。按照目前的情况,我的uwp程序集可能只会增长到大约2到3打项,然后它们就需要很长的时间来编译了。当您尝试进行迭代编码和调试时,任何需要10秒以上时间来编译的程序集都是有问题的。

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

    接下来要做的是用procmon监视构建操作。这将暴露出任何特定于您的工作站的问题(如病毒扫描、其他可能干扰的应用程序)。

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

    • 许多编译过程(请参见生成输出窗口中的过程):
    > MarkupCompilePass1:
    > XamlPreCompile:
    > MarkupCompilePass2:
    > GenerateTargetFrameworkMonikerAttribute:
    > CoreCompile:
    > CopyGeneratedXaml:
    > CopyFilesToOutputDirectory:
    > ComputeProcessXamlFiles:
    > CustomOutputGroupForPackaging:
    > GetPackagingOutputs:
    > _GenerateProjectPriConfigurationFiles:
    > _GenerateProjectPriFileCore:
    
    • 核心/核心依赖项

    与.NET框架不同,您对uwp的所有依赖项都来自.NET核心和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所做的工作中,有不到一半是专门为我完成的。它的其余部分引入了所有依赖项,这样我的代码就可以针对它进行编译。必须有一种方法来优化这种重复处理。

        2
  •  0
  •   David Beavon    7 年前

    罗南(12秒?)空项目的编译时间确实有点高…我的通常运行时间不到5秒(空的时候)。

    您可能想观察CPU的情况。在文件系统缓存了源代码(并且下载了所有nuget依赖项)之后,单个项目的编译应该完全受CPU限制,尤其是在第二次或第三次尝试时。您可能需要关注任务管理器,并确保在单个核心上以全速运行(即,如果您有四个核心,则为25%,对于八个核心,则为12%)等。如果你看到CPU掉得太远,那么就有问题了。还要确保检查CPU 只有 通常情况下会用到,例如devenv.exe、vbccompiler.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 以下是我的结果:

    • 库存应用程序14秒

    Vanarsdel示例应用程序将是另一个很好的基准应用程序。(小心这一点;你可能不得不在一个Windows的内部版本,它可能会像我的一样把你的vs搞乱)。网址如下: https://github.com/microsoft/vanarsdel 以下是我的结果:

    • Vanarsdel项目13秒

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

    使用诊断输出

    虽然构建项目所用的总时间非常关键,但了解时间的来源可能也很有帮助。如果转到“工具”->“选项”->“生成并运行”,然后将“项目生成输出详细信息”设置为“诊断”,则可以获得此摘要。然后编译相关的项目。最后,您将看到一个任务性能摘要,如下所示。请注意,compileXML应该花费最多的时间。这五项似乎很常见。

    任务性能摘要:

      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)占用了几秒钟,那么这可能是项目中的损坏问题。您应该能够通过搜索单词“完全”进行故障排除,如“完全构建目标”中的“生成当前项目Appxmanifest”。当你发现的时候,它应该告诉你为什么要做额外的工作。

    最小版本目标

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

    请参见下面将min version更改为15063有助于缩短编译时间。我怀疑这与相关依赖项中的膨胀有关。

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

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