Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
自从上次生成解决方案以来,没有任何更改,为什么msbuild速度如此之慢?_Msbuild_Devenv - Fatal编程技术网

自从上次生成解决方案以来,没有任何更改,为什么msbuild速度如此之慢?

自从上次生成解决方案以来,没有任何更改,为什么msbuild速度如此之慢?,msbuild,devenv,Msbuild,Devenv,我有109个项目的解决方案。混合了.NET、Silverlight、MVC、Web应用程序和控制台应用程序 现在,我使用msbuild在控制台上构建它。这需要一些时间。可以理解-很多项目,很多文件 但是,当我在第一次之后第二次构建它时——即使没有实际构建任何内容,它仍然需要很多时间——diag msbuild日志确认了这一点 例如,以下是第一次完整生成的任务性能摘要: Task Performance Summary: 4 ms GetSilverlightItemsFromPrope

我有109个项目的解决方案。混合了.NET、Silverlight、MVC、Web应用程序和控制台应用程序

现在,我使用msbuild在控制台上构建它。这需要一些时间。可以理解-很多项目,很多文件

但是,当我在第一次之后第二次构建它时——即使没有实际构建任何内容,它仍然需要很多时间——diag msbuild日志确认了这一点

例如,以下是第一次完整生成的任务性能摘要:

Task Performance Summary:
    4 ms  GetSilverlightItemsFromProperty            1 calls
   13 ms  Move                                       1 calls
   20 ms  GetReferenceAssemblyPaths                 27 calls
   28 ms  GetFrameworkPath                         190 calls
   29 ms  ValidateSilverlightFrameworkPaths        163 calls
   72 ms  AssignCulture                            192 calls
   75 ms  ResolveKeySource                         179 calls
   79 ms  MakeDir                                  200 calls
   95 ms  CreateProperty                           260 calls
  100 ms  CreateCSharpManifestResourceName         122 calls
  102 ms  Delete                                   442 calls
  112 ms  GenerateResource                           3 calls
  123 ms  CopyFilesToFolders                         1 calls
  177 ms  ReadLinesFromFile                        190 calls
  179 ms  CreateHtmlTestPage                        31 calls
  181 ms  CallTarget                               190 calls
  184 ms  GetSilverlightFrameworkPath              163 calls
  211 ms  Message                                  573 calls
  319 ms  CreateSilverlightAppManifest              97 calls
  354 ms  FileClassifier                           119 calls
  745 ms  ConvertToAbsolutePath                    190 calls
  868 ms  PackagePlatformExtensions                 94 calls
  932 ms  AssignProjectConfiguration               190 calls
 1625 ms  CategorizeSilverlightReferences          163 calls
 1722 ms  ResourcesGenerator                        60 calls
 2467 ms  WriteLinesToFile                         118 calls
 5589 ms  RemoveDuplicates                         380 calls
 8207 ms  FindUnderPath                            950 calls
17720 ms  XapPackager                               97 calls
38162 ms  Copy                                     857 calls
38934 ms  CompileXaml                              119 calls
40567 ms  Exec                                      14 calls
55275 ms  ValidateXaml                             119 calls
65845 ms  AssignTargetPath                         1140 calls
83792 ms  Csc                                      108 calls
105906 ms  ResolveAssemblyReference                 190 calls
1163988 ms  MSBuild                                  471 calls
msbuild声明
经过的时间00:08:39.44

好的。现在,我再次运行相同的命令行并获得以下结果:

Task Performance Summary:
    1 ms  GetSilverlightItemsFromProperty            1 calls
   11 ms  WriteLinesToFile                           1 calls
   17 ms  GetReferenceAssemblyPaths                 27 calls
   24 ms  GetFrameworkPath                         190 calls
   32 ms  ValidateSilverlightFrameworkPaths        163 calls
   43 ms  CopyFilesToFolders                         1 calls
   47 ms  GenerateResource                           3 calls
   60 ms  ResolveKeySource                         179 calls
   66 ms  MakeDir                                  200 calls
   69 ms  AssignCulture                            192 calls
   70 ms  PackagePlatformExtensions                 94 calls
   76 ms  Delete                                   432 calls
   89 ms  CreateProperty                           260 calls
   98 ms  CreateCSharpManifestResourceName         122 calls
  136 ms  GetSilverlightFrameworkPath              163 calls
  156 ms  CallTarget                               190 calls
  182 ms  CreateHtmlTestPage                        31 calls
  207 ms  XapPackager                               97 calls
  215 ms  ReadLinesFromFile                        190 calls
  217 ms  Message                                  573 calls
  271 ms  CreateSilverlightAppManifest              97 calls
  350 ms  FileClassifier                           119 calls
  526 ms  ConvertToAbsolutePath                    190 calls
  795 ms  AssignProjectConfiguration               190 calls
 1658 ms  CategorizeSilverlightReferences          163 calls
 2237 ms  Exec                                       2 calls
 5703 ms  RemoveDuplicates                         380 calls
 6948 ms  Copy                                     426 calls
 7550 ms  FindUnderPath                            950 calls
17126 ms  CompileXaml                              119 calls
54495 ms  ValidateXaml                             119 calls
78953 ms  AssignTargetPath                         1140 calls
97374 ms  ResolveAssemblyReference                 190 calls
603295 ms  MSBuild                                  471 calls
msbuild声明
经过的时间00:05:25.70

这就提出了以下问题:

  • 为什么
    resolvesassemblyReference
    在第二次构建中花费了这么多时间?在第一次生成中创建的所有缓存文件仍然存在。一切都没有改变。那么,为什么它花费的时间几乎和以前一样——97秒对106秒
  • 为什么
    ValidateXaml
    CompileXaml
    正在运行?我的意思是,自从全面建设以来,一切都没有改变 现在我重复同样的实验,但这次我在命令行上使用
    devenv
    而不是
    msbuild
    进行构建。与msbuild一样,不使用并行生成,并且日志级别在diag上

    devenv
    最后没有给出这么好的摘要,它必须从每个项目的摘要中手动汇总

    结果令我惊讶。我使用以下powershell脚本来聚合运行时间:

    Param(
      [Parameter(Mandatory=$True,Position=1)][string]$log
    )
    [timespan]::FromMilliseconds((sls -SimpleMatch "Time Elapsed" $log |% {[timespan]::Parse(($_ -split ' ')[2]) } | measure -Sum TotalMilliseconds).Sum).ToString()
    
    使用命令行上的
    devenv
    从完全相同的站点构建完全相同的解决方案,第一次构建需要
    00:06:10.9000000
    ,第二次构建需要
    00:00:03.1000000
    只需3秒

    我还编写了一个powershell脚本来汇总统计数据:

    Param(
      [Parameter(Mandatory=$True,Position=1)][string]$log
    )
    $summary=@{}
    cat $log |% { 
      if ($collect) {
        if ($_ -eq "") {
          $collect = $false;
        } else { 
          $tmp = ($_ -replace '\s+', ' ') -split ' ';
          $cur = $summary[$tmp[3]];
          if (!$cur) { 
            $cur = @(0, 0);
            $summary[$tmp[3]] = $cur;
          }
          $cur[0] += $tmp[1];
          $cur[1] += $tmp[4];
        }
      } else { 
        $collect = $_ -eq "Task Performance Summary:" 
      } 
    }
    $summary.Keys |% {
      $stats = $summary[$_];
      $ms = $stats[0];
      $calls = $stats[1];
      [string]::Format("{0,10} ms {1,-40} {2} calls", $ms,$_,$calls);
    } | sort
    
    在第一个(完整)构建的日志上运行它会产生以下输出:

         5 ms ValidateSilverlightFrameworkPaths        82 calls
         7 ms Move                                     1 calls
         9 ms GetFrameworkPath                         108 calls
        11 ms GetReferenceAssemblyPaths                26 calls
        14 ms AssignCulture                            109 calls
        16 ms ReadLinesFromFile                        108 calls
        18 ms CreateCSharpManifestResourceName         61 calls
        18 ms ResolveKeySource                         97 calls
        23 ms Delete                                   268 calls
        26 ms CreateProperty                           131 calls
        41 ms MakeDir                                  118 calls
        66 ms CallTarget                               108 calls
        70 ms Message                                  326 calls
        75 ms ResolveNonMSBuildProjectOutput           104 calls
       101 ms GenerateResource                         1 calls
       107 ms GetSilverlightFrameworkPath              82 calls
       118 ms CreateHtmlTestPage                       16 calls
       153 ms FileClassifier                           60 calls
       170 ms CreateSilverlightAppManifest             49 calls
       175 ms AssignProjectConfiguration               108 calls
       279 ms ConvertToAbsolutePath                    108 calls
       891 ms CategorizeSilverlightReferences          82 calls
       926 ms PackagePlatformExtensions                47 calls
      1291 ms ResourcesGenerator                       60 calls
      2193 ms WriteLinesToFile                         108 calls
      3687 ms RemoveDuplicates                         216 calls
      5538 ms FindUnderPath                            540 calls
      6157 ms MSBuild                                  294 calls
     16496 ms Exec                                     4 calls
     19699 ms XapPackager                              49 calls
     21281 ms Copy                                     378 calls
     28362 ms ValidateXaml                             60 calls
     29526 ms CompileXaml                              60 calls
     66846 ms AssignTargetPath                         654 calls
     81650 ms Csc                                      108 calls
     82759 ms ResolveAssemblyReference                 108 calls
    
    现在,对于第二次构建,结果如下:

         1 ms AssignCulture                            1 calls
         1 ms CreateProperty                           1 calls
         1 ms Delete                                   2 calls
         1 ms ValidateSilverlightFrameworkPaths        1 calls
         3 ms AssignTargetPath                         6 calls
         3 ms ConvertToAbsolutePath                    1 calls
         3 ms PackagePlatformExtensions                1 calls
         3 ms ReadLinesFromFile                        1 calls
         3 ms ResolveKeySource                         1 calls
         4 ms ResolveNonMSBuildProjectOutput           1 calls
         5 ms CreateCSharpManifestResourceName         1 calls
         5 ms GetFrameworkPath                         1 calls
        10 ms CategorizeSilverlightReferences          1 calls
        11 ms CallTarget                               1 calls
        11 ms FileClassifier                           1 calls
        11 ms FindUnderPath                            5 calls
        11 ms MakeDir                                  1 calls
        13 ms Copy                                     2 calls
        17 ms GetSilverlightFrameworkPath              1 calls
        17 ms RemoveDuplicates                         2 calls
        30 ms AssignProjectConfiguration               1 calls
        32 ms Message                                  25 calls
       239 ms ResolveAssemblyReference                 1 calls
       351 ms MSBuild                                  2 calls
       687 ms CompileXaml                              1 calls
      1413 ms ValidateXaml                             1 calls
    
    我们在这里讨论的是完全相同的解决方案

    最后,以下是我使用解决方案构建的脚本:

    msbuild:

    @setlocal
    
    set SHELFSET=msbuild
    
    set MSBUILDLOGVERBOSERARSEARCHRESULTS=true
    set AppConfig=app.config
    set Disable_CopyWebApplication=true
    set MvcBuildViews=false
    
    call \tmp\undo.cmd
    del /a:-R /s/q *.*
    tf unshelve %SHELFSET% /recursive /noprompt
    
    msbuild DataSvc.sln
    msbuild Main.sln /v:diag > \tmp\00.Main.msbuild.full.log
    msbuild Main.sln /v:diag > \tmp\01.Main.msbuild.incr.log
    msbuild Main.sln /v:diag > \tmp\02.Main.msbuild.incr.log
    
    @endlocal
    
    @setlocal
    
    set SHELFSET=msbuild
    
    set MSBUILDLOGVERBOSERARSEARCHRESULTS=true
    set AppConfig=app.config
    set Disable_CopyWebApplication=true
    set MvcBuildViews=false
    
    call \tmp\undo.cmd
    del /a:-R /s/q *.*
    tf unshelve %SHELFSET% /recursive /noprompt
    
    msbuild DataSvc.sln
    devenv  Main.sln /build > \tmp\00.Main.devenv.full.log
    devenv  Main.sln /build > \tmp\01.Main.devenv.incr.log
    devenv  Main.sln /build > \tmp\02.Main.devenv.incr.log
    
    @endlocal
    
    devenv:

    @setlocal
    
    set SHELFSET=msbuild
    
    set MSBUILDLOGVERBOSERARSEARCHRESULTS=true
    set AppConfig=app.config
    set Disable_CopyWebApplication=true
    set MvcBuildViews=false
    
    call \tmp\undo.cmd
    del /a:-R /s/q *.*
    tf unshelve %SHELFSET% /recursive /noprompt
    
    msbuild DataSvc.sln
    msbuild Main.sln /v:diag > \tmp\00.Main.msbuild.full.log
    msbuild Main.sln /v:diag > \tmp\01.Main.msbuild.incr.log
    msbuild Main.sln /v:diag > \tmp\02.Main.msbuild.incr.log
    
    @endlocal
    
    @setlocal
    
    set SHELFSET=msbuild
    
    set MSBUILDLOGVERBOSERARSEARCHRESULTS=true
    set AppConfig=app.config
    set Disable_CopyWebApplication=true
    set MvcBuildViews=false
    
    call \tmp\undo.cmd
    del /a:-R /s/q *.*
    tf unshelve %SHELFSET% /recursive /noprompt
    
    msbuild DataSvc.sln
    devenv  Main.sln /build > \tmp\00.Main.devenv.full.log
    devenv  Main.sln /build > \tmp\01.Main.devenv.incr.log
    devenv  Main.sln /build > \tmp\02.Main.devenv.incr.log
    
    @endlocal
    
    我的测试告诉我,
    msbuild
    是一堆垃圾,我不应该在命令行中使用它来构建我的C#解决方案。增加了这种感觉

    但也许我说错了,一个简单的调整将使msbuild在第二次构建中与
    devenv
    一样高效

    如何让msbuild在第二次构建中正常运行

    编辑1

    CompileXaml
    任务是在C:\Program Files(x86)\MSBuild\Microsoft\Silverlight\v5.0\Microsoft.Silverlight.Common.targets中找到的
    MarkupCompilePass1
    目标的一部分:

    <Target Name="MarkupCompilePass1"
          DependsOnTargets="$(CompileXamlDependsOn)" 
          Condition="'@(Page)@(ApplicationDefinition)' != '' " >
    
        <CompileXaml 
               LanguageSourceExtension="$(DefaultLanguageSourceExtension)"
               Language="$(Language)" 
               SilverlightPages="@(Page)" 
               SilverlightApplications="@(ApplicationDefinition)" 
               ProjectPath="$(MSBuildProjectFullPath)"
               RootNamespace="$(RootNamespace)"
               AssemblyName="$(AssemblyName)" 
               OutputPath="$(IntermediateOutputPath)"
               SkipLoadingAssembliesInXamlCompiler="$(SkipLoadingAssembliesInXamlCompiler)"
               TargetFrameworkDirectory="$(TargetFrameworkDirectory)" 
               TargetFrameworkSDKDirectory="$(TargetFrameworkSDKDirectory)"
               ReferenceAssemblies ="@(ReferencePath);@(InferredReference->'$(TargetFrameworkDirectory)\%(Identity)')"
               >
    
            <Output ItemName="Compile" TaskParameter="GeneratedCodeFiles" />
    
            <!-- Add to the list list of files written. It is used in Microsoft.Common.Targets to clean up 
                 for a next clean build 
              -->
            <Output ItemName="FileWrites" TaskParameter="GeneratedCodeFiles" />
            <Output ItemName="_GeneratedCodeFiles" TaskParameter="GeneratedCodeFiles" />
    
        </CompileXaml>
    
        <Message Text="(Out) GeneratedCodeFiles: '@(_GeneratedCodeFiles)'" Condition="'$(MSBuildTargetsVerbose)'=='true'"/>
    </Target>
    
    
    
    正如我们所见,没有输入也没有输出

    接下来,第二个生成的diag msbuild日志不包含任何可疑的单词,如“rebuilding”

    最后,我想指出,msbuild和devenv都是在完全相同的环境下运行的,没有一个使用多线程构建。然而,两者之间的差异是巨大的——超过5分钟(msbuild)而不是3秒(devenv,命令行)

    对我来说仍然是个谜

    编辑2

    我现在更了解devenvbuild的工作原理。它使用启发式方法来确定当前项目是否必须首先移交给msbuild。默认情况下会启用此启发式,但可以通过将
    disableFastUpdateCheck
    msbuild属性设置为
    true
    来禁用此启发式

    现在,命令行devenv构建实际上需要3秒钟以上的时间来确定是否需要运行msbuild。总而言之,对于像我这样的解决方案,可能需要20秒甚至30秒才能确定不需要向msbuild传递任何内容

    这种启发是造成时间上巨大差异的唯一原因。我猜VisualStudio团队意识到标准构建脚本的质量很差(MarkupCompilePass1之类的任务不是由输入和输出驱动的),并决定首先想出一种跳过msbuild的方法

    但是有一个陷阱——启发式只检查csproj文件,没有检查导入的目标文件。此外,它对隐式依赖项一无所知,比如从其他TypeScript文件引用的TypeScript文件。因此,如果您的TypeScript文件引用了属于不同项目的其他TypeScript文件,并且没有从项目文件显式链接到其他TypeScript文件,则启发式方法不知道这些文件,您最好使用
    disableFastUpdateCheck=true
    。构建速度会较慢,但至少是正确的


    底线-我不知道如何修复msbuild,显然devenv的家伙也不知道。这似乎就是他们发明启发式的原因。

    首先,看看你正在生成的诊断日志。实际上,首先使用文件记录器而不是控制台操作符将控制台输出管道传输到日志,然后查看它们的日志

    实际上,使用以下命令代替
    /v:diag>msbuild.log

    /v:min /fl3 /flp3:warningsonly;logfile=msbuild.wrn /fl4 /flp4:errorsOnly;logfile=msbuild.err /fl5 /flp5:Verbosity=diag;logfile=msbuild.log
    
    现在,您的控制台缓冲区感谢您,您的开发人员也感谢您为调试提供了仅保留单独的错误日志和仅警告日志的远见

    现在,检查诊断MsBuild日志,并在CTRL+F中查找运行时间较长的目标。您是否看到任何表示目标再次运行的措辞,即使没有任何更改?要跳过构建,目标需要定义输入和输出。如果输入(.cs)比输出(.dll、.pdb)新,那么它知道一定有什么东西发生了变化