我注意到我们的SSDT项目通过TFS构建定义的构建要比通过本地开发工具箱上的VS 2013的构建慢得多。

在构建服务器本身上,我可以在大约2分钟内通过VS 2013构建我们最大的SSDT项目。使用MSBuild在同一服务器上从命令行在同一服务器上构建完全相同的项目,大约需要16分钟(即以与TFS构建定义相同的方式构建SSDT项目)

我已经从两种方法中收集了/verbosity:diagnostic输出,但是我一生都看不到提供给MSBuild的参数有任何实质性的区别。

在VS 2013中,配置为Debug:AnyCPU。

我使用的MSBuild命令是:

msbuild/t:重建/p:配置=调试/p:平台= AnyCPU .sqlproj

我在较小的SSDT项目上尝试了相同的过程,并且在构建时间上也得到了类似的相对差异(例如,另一个项目在VS 2013中花费了10秒,而在MSBuild中花费了70-80秒)

我拥有VS 2013(12.0.40629.00 Update 5)和SSDT(12.0.60629.0)的最新版本

有没有其他人看到过这个问题,或者甚至有解决此问题的方法?

转向VS 2015是否可以解决问题?

已编辑以回复评论并包含诊断信息-15-08-2016

谢谢你们给我的建议。

埃德,当针对MSBuild测试VS时,我使用了构建目标Rebuild,我相信它是Clean和Build的结合。在TFS构建定义中,我将“清理工作区”和“清理构建”设置为true,但是“获取源代码”步骤的时间仅为9秒。

史蒂文(Steven),dbmdl因素听起来确实很有希望。但是,在从解决方案中删除所有dbmdl文件之后,我再次尝试了测试,但我仍然得到相同的时间(我验证了dbmdl文件没有在测试版本之间重新生成)。另外,在测试之前,我已经删除了所有bin和obj文件夹,只是为了消除VS构建缓存数据的任何可能性。

Cece,我已经有效地从这个问题中删除了TFS,因为在测试VS和MSBuild时,我在构建时间上存在差异。我认为,如果我能破解的话,TFS的构建时间也会被破解。您对花费时间在哪个构建步骤上有个很好的认识。我不想在最初的文章中充斥过多的信息,但是现在是时候了:-)。我使用了/clp:PerformanceSummary选项来获得花费时间的分割。

在下面的第1节中,您可以看到“SqlBuildTask”中的时间几乎全部用完了。很高兴知道,但对查明问题不是很有帮助。

在第2和第3节中,我使用/verbosity:diagnostic输出从两种构建方法中获得的信息

我看不到两个版本之间的任何实质性区别。两者都必须使用此DLL来执行该实际生成(MSBuild显式声明对此DLL的引用):

 C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\\Extensions\Microsoft\SQLDB\Dac\130\Microsoft.Data.Tools.Schema.Tasks.Sql.dll"

-------------第1节-------------

(使用/clp:PerformanceSummary从MSBuild输出)
Project Performance Summary:
        82518 ms  P:\<snip>.sqlproj   1 calls
                  82518 ms  rebuild                                    1 calls

Target Performance Summary:
        0 ms  BuildOnlySettings                          2 calls
        0 ms  GetReferenceAssemblyPaths                  2 calls
        0 ms  GetSqlSymbolsPath                          1 calls
        0 ms  BeforeBuild                                2 calls
        0 ms  ResolveReferences                          2 calls
        0 ms  GetCopyToOutputDirectoryXamlAppDefs        2 calls
        0 ms  SqlStudioSourceFilesToCopy                 2 calls
        0 ms  AssignProjectConfiguration                 1 calls
        0 ms  BeforeClean                                2 calls
        0 ms  _CopySourceItemsToOutputDirectory          2 calls
        0 ms  Build                                      2 calls
        0 ms  GetCopyToOutputDirectoryItems              2 calls
        0 ms  Clean                                      2 calls
        0 ms  CleanPublishFolder                         2 calls
        0 ms  GetFrameworkPaths                          2 calls
        0 ms  GetTargetPath                              2 calls
        0 ms  _CleanGetCurrentAndPriorFileWrites         2 calls
        0 ms  _CopyFilesMarkedCopyLocal                  1 calls
        0 ms  AfterResolveReferences                     2 calls
        0 ms  PreXsdCodeGen                              2 calls
        0 ms  CopyFilesToOutputDirectory                 2 calls
        0 ms  GetNativeManifest                          1 calls
        0 ms  GetInstalledSDKLocations                   2 calls
        0 ms  IncrementalClean                           2 calls
        0 ms  PrepareForRun                              2 calls
        0 ms  _SplitProjectReferencesByFileExistence     2 calls
        0 ms  _SetupSqlBuildOutputs                      2 calls
        0 ms  BeforeResolveReferences                    2 calls
        0 ms  GetSqlTargetPath                           1 calls
        0 ms  Rebuild                                    1 calls
        0 ms  AfterClean                                 2 calls
        0 ms  AfterBuild                                 2 calls
        0 ms  ExpandSDKReferences                        2 calls
        0 ms  CleanStaticCodeAnalysis                    2 calls
        0 ms  BeforeRebuild                              1 calls
        0 ms  CheckRequiredProperties                    2 calls
        0 ms  GenerateSqlTargetFrameworkMoniker          2 calls
        0 ms  ResolveSDKReferences                       2 calls
        0 ms  AfterRebuild                               1 calls
        0 ms  ResolveArtifactReferences                  2 calls
        0 ms  _CopyOutOfDateSourceItemsToOutputDirectoryAlways   1 calls
        0 ms  _CheckForCompileOutputs                    2 calls
        0 ms  PrepareForBuild                            2 calls
        0 ms  CleanXsdCodeGen                            2 calls
       16 ms  _CheckForInvalidConfigurationAndPlatform   2 calls
       16 ms  AssignTargetPaths                          2 calls
       16 ms  CoreClean                                  2 calls
       31 ms  ResolveAssemblyReferences                  2 calls
       31 ms  SqlPrepareForRun                           2 calls
       31 ms  CleanReferencedProjects                    2 calls
       63 ms  PostBuildEvent                             2 calls
       63 ms  PreBuildEvent                              2 calls
       94 ms  CoreCompile                                2 calls
      625 ms  _SetupSqlBuildInputs                       2 calls
     6452 ms  ResolveProjectReferences                   2 calls
    81502 ms  SqlBuild                                   2 calls

Task Performance Summary:
        0 ms  AssignTargetPath                          26 calls
        0 ms  CallTarget                                 2 calls
        0 ms  FindAppConfigFile                          2 calls
        0 ms  ConvertToAbsolutePath                      2 calls
        0 ms  AssignProjectConfiguration                 1 calls
        0 ms  ReadLinesFromFile                          4 calls
        0 ms  WriteLinesToFile                           4 calls
        0 ms  Copy                                       6 calls
        0 ms  FindUnderPath                             14 calls
        0 ms  RemoveDuplicates                           6 calls
        0 ms  MakeDir                                    4 calls
       16 ms  SqlScriptDependenciesTask                  2 calls
       16 ms  Delete                                    12 calls
       31 ms  ResolveAssemblyReference                   2 calls
       31 ms  Message                                    8 calls
       94 ms  Csc                                        1 calls
      126 ms  Exec                                       4 calls
      516 ms  SqlModelResolutionTask                     2 calls
     6468 ms  MSBuild                                    7 calls
    81424 ms  SqlBuildTask                               2 calls

-------------第2节-------------

(在VS构建的SqlBuildTask阶段给出的诊断输出)
Target "SqlBuild" in file "C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v12.0\SSDT\Microsoft.Data.Tools.Schema.SqlTasks.targets" from project "P:<snip>.sqlproj" (target "Build" depends on it):
    Building target "SqlBuild" completely.
    Output file "P:<snip>.dacpac" does not exist.
    Task "SqlBuildTask"
        Task Parameter:SqlTarget=P:<snip>.dacpac
        Task Parameter:ContributorArguments=ConfigurationName=Debug;
        Task Parameter:BuildContributors=;
        Task Parameter:DeploymentContributors=;
        Task Parameter:CreateScriptFileName=<snip>.sql
        Task Parameter:DacApplicationName=<snip>
        Task Parameter:DacDescription=<snip>
        Task Parameter:DacFile=P:<snip>\bin\Debug\
        Task Parameter:DacVersion=3.27.0.0
        Task Parameter:DatabaseName=<snip>
        Task Parameter:DatabaseSchemaProviderName=Microsoft.Data.Tools.Schema.Sql.Sql100DatabaseSchemaProvider
        Task Parameter:DefaultSchema=dbo
        Task Parameter:DeploymentScriptName=<snip>.sql
        Task Parameter:DeployToDatabase=True
        Task Parameter:ImplicitDllAssemblyName=<snip>
        Task Parameter:ImplicitDllFileName=P:<snip>.dll
        Task Parameter:ImplicitDllSymbolsFileName=P:<snip>.pdb
        Task Parameter:ImplicitDllGenerateSqlClrDdl=true
        Task Parameter:IntermediateDirectory=P:<snip>\obj\Debug\
        Task Parameter:ModelCollation=1033,CI
        Task Parameter:OutputDirectory=P:<snip>\bin\Debug\
        Task Parameter:
    Source= <snip - list of all the source files in the SSDT project - matches list for MSBuild builds>

        Task Parameter:
    SqlCmdVariables= <snip - same for both builds>
        Task Parameter:
    SqlReferencePath=
        C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\mscorlib.dll
                CopyLocal=false
                FrameworkFile=true
                FusionName=mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
                ImageRuntime=v4.0.30319
                OriginalItemSpec=C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\mscorlib.dll
                ReferenceSourceTarget=ResolveAssemblyReference
                ResolvedFrom=C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\mscorlib.dll
                Version=4.0.0.0
        Task Parameter:SuppressTSqlWarnings=71562,71502,71558
        Task Parameter:ValidateCasingOnIdentifiers=true
        Task Parameter:CmdLineInMemoryStorage=false
        Task Parameter:DefaultCollation=SQL_Latin1_General_CP1_CI_AS
        Task Parameter:AnsiNullDefault=False
        Task Parameter:AnsiNulls=False
        Task Parameter:AnsiPadding=False
        Task Parameter:AnsiWarnings=False
        Task Parameter:ArithAbort=False
        Task Parameter:ConcatNullYieldsNull=False
        Task Parameter:QuotedIdentifier=False
        Task Parameter:NumericRoundAbort=False
        Task Parameter:RecursiveTriggersEnabled=False
        Task Parameter:DatabaseChaining=False
        Task Parameter:DatabaseState=ONLINE
        Task Parameter:CloseCursorOnCommitEnabled=False
        Task Parameter:DefaultCursor=GLOBAL
        Task Parameter:AutoClose=False
        Task Parameter:AutoCreateStatistics=True
        Task Parameter:AutoShrink=False
        Task Parameter:AutoUpdateStatistics=True
        Task Parameter:TornPageDetection=False
        Task Parameter:DatabaseAccess=MULTI_USER
        Task Parameter:Recovery=FULL
        Task Parameter:EnableFullTextSearch=False
        Task Parameter:DefaultFilegroup=PRIMARY
        Task Parameter:Trustworthy=True
        Task Parameter:AutoUpdateStatisticsAsynchronously=False
        Task Parameter:PageVerify=CHECKSUM
        Task Parameter:ServiceBrokerOption=DisableBroker
        Task Parameter:DateCorrelationOptimizationOn=False
        Task Parameter:Parameterization=SIMPLE
        Task Parameter:AllowSnapshotIsolation=False
        Task Parameter:ReadCommittedSnapshot=True
        Task Parameter:VardecimalStorageFormatOn=True
        Task Parameter:SupplementalLoggingOn=False
        Task Parameter:CompatibilityMode=100
        Task Parameter:IsChangeTrackingOn=False
        Task Parameter:IsChangeTrackingAutoCleanupOn=True
        Task Parameter:ChangeTrackingRetentionPeriod=2
        Task Parameter:ChangeTrackingRetentionUnit=Days
        Task Parameter:IsEncryptionOn=False
        Task Parameter:IsBrokerPriorityHonored=False
        Task Parameter:IncludeCompositeObjects=True
        Loading project references...
        Loading project files...
        Building the project model and resolving object interdependencies...
        Validating the project model...
        Writing model to P:<snip>\obj\Debug\Model.xml...

-------------第3节-------------

(在MSBuild构建的SqlBuildTask阶段给出的诊断输出)
Target "SqlBuild: (TargetId:68)" in file "C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v12.0\SSDT\Microsoft.Data.Tools.Schema.SqlTasks.targets" from project "P:<snip>.sqlproj" (target "Build" depends on it):
Building target "SqlBuild" completely.
Output file "P:<snip>.dacpac" does not exist.
Using "SqlBuildTask" task from assembly "C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\\Extensions\Microsoft\SQLDB\Dac\130\Microsoft.Data.Tools.Schema.Tasks.Sql.dll".
Task "SqlBuildTask" (TaskId:56)
  Task Parameter:SqlTarget=P:<snip>.dacpac (TaskId:56)
  Task Parameter:ContributorArguments=ConfigurationName=Debug; (TaskId:56)
  Task Parameter:BuildContributors=; (TaskId:56)
  Task Parameter:DeploymentContributors=; (TaskId:56)
  Task Parameter:CreateScriptFileName=<snip>.sql (TaskId:56)
  Task Parameter:DacApplicationName=<snip> (TaskId:56)
  Task Parameter:DacDescription=<snip> (TaskId:56)
  Task Parameter:DacFile=P:<snip>\bin\Debug\ (TaskId:56)
  Task Parameter:DacVersion=3.27.0.0 (TaskId:56)
  Task Parameter:DatabaseName=<snip> (TaskId:56)
  Task Parameter:DatabaseSchemaProviderName=Microsoft.Data.Tools.Schema.Sql.Sql100DatabaseSchemaProvider (TaskId:56)
  Task Parameter:DefaultSchema=dbo (TaskId:56)
  Task Parameter:DeploymentScriptName=<snip>.sql (TaskId:56)
  Task Parameter:DeployToDatabase=True (TaskId:56)
  Task Parameter:ImplicitDllAssemblyName=<snip> (TaskId:56)
  Task Parameter:ImplicitDllFileName=P:<snip>.dll (TaskId:56)
  Task Parameter:ImplicitDllSymbolsFileName=P:<snip>.pdb (TaskId:56)
  Task Parameter:ImplicitDllGenerateSqlClrDdl=true (TaskId:56)
  Task Parameter:IntermediateDirectory=P:<snip>\obj\Debug\ (TaskId:56)
  Task Parameter:ModelCollation=1033,CI (TaskId:56)
  Task Parameter:OutputDirectory=P:<snip>\bin\Debug\ (TaskId:56)
  Task Parameter:
      Source= <snip - list of all the source files in the SSDT project - matches list for VS builds>
  Task Parameter:
      SqlCmdVariables= <snip - same for both builds>
  Task Parameter:
      SqlReferencePath=
          C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\mscorlib.dll
                  CopyLocal=false
                  FrameworkFile=true
                  FusionName=mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
                  ImageRuntime=v4.0.30319
                  OriginalItemSpec=C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\mscorlib.dll
                  ReferenceSourceTarget=ResolveAssemblyReference
                  ResolvedFrom=C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\mscorlib.dll
                  Version=4.0.0.0 (TaskId:56)
  Task Parameter:SuppressTSqlWarnings=71562,71502,71558 (TaskId:56)
  Task Parameter:ValidateCasingOnIdentifiers=true (TaskId:56)
  Task Parameter:CmdLineInMemoryStorage=false (TaskId:56)
  Task Parameter:DefaultCollation=SQL_Latin1_General_CP1_CI_AS (TaskId:56)
  Task Parameter:AnsiNullDefault=False (TaskId:56)
  Task Parameter:AnsiNulls=False (TaskId:56)
  Task Parameter:AnsiPadding=False (TaskId:56)
  Task Parameter:AnsiWarnings=False (TaskId:56)
  Task Parameter:ArithAbort=False (TaskId:56)
  Task Parameter:ConcatNullYieldsNull=False (TaskId:56)
  Task Parameter:QuotedIdentifier=False (TaskId:56)
  Task Parameter:NumericRoundAbort=False (TaskId:56)
  Task Parameter:RecursiveTriggersEnabled=False (TaskId:56)
  Task Parameter:DatabaseChaining=False (TaskId:56)
  Task Parameter:DatabaseState=ONLINE (TaskId:56)
  Task Parameter:CloseCursorOnCommitEnabled=False (TaskId:56)
  Task Parameter:DefaultCursor=GLOBAL (TaskId:56)
  Task Parameter:AutoClose=False (TaskId:56)
  Task Parameter:AutoCreateStatistics=True (TaskId:56)
  Task Parameter:AutoShrink=False (TaskId:56)
  Task Parameter:AutoUpdateStatistics=True (TaskId:56)
  Task Parameter:TornPageDetection=False (TaskId:56)
  Task Parameter:DatabaseAccess=MULTI_USER (TaskId:56)
  Task Parameter:Recovery=FULL (TaskId:56)
  Task Parameter:EnableFullTextSearch=False (TaskId:56)
  Task Parameter:DefaultFilegroup=PRIMARY (TaskId:56)
  Task Parameter:Trustworthy=True (TaskId:56)
  Task Parameter:AutoUpdateStatisticsAsynchronously=False (TaskId:56)
  Task Parameter:PageVerify=CHECKSUM (TaskId:56)
  Task Parameter:ServiceBrokerOption=DisableBroker (TaskId:56)
  Task Parameter:DateCorrelationOptimizationOn=False (TaskId:56)
  Task Parameter:Parameterization=SIMPLE (TaskId:56)
  Task Parameter:AllowSnapshotIsolation=False (TaskId:56)
  Task Parameter:ReadCommittedSnapshot=True (TaskId:56)
  Task Parameter:VardecimalStorageFormatOn=True (TaskId:56)
  Task Parameter:SupplementalLoggingOn=False (TaskId:56)
  Task Parameter:CompatibilityMode=100 (TaskId:56)
  Task Parameter:IsChangeTrackingOn=False (TaskId:56)
  Task Parameter:IsChangeTrackingAutoCleanupOn=True (TaskId:56)
  Task Parameter:ChangeTrackingRetentionPeriod=2 (TaskId:56)
  Task Parameter:ChangeTrackingRetentionUnit=Days (TaskId:56)
  Task Parameter:IsEncryptionOn=False (TaskId:56)
  Task Parameter:IsBrokerPriorityHonored=False (TaskId:56)
  Task Parameter:IncludeCompositeObjects=True (TaskId:56)
  Creating a model to represent the project... (TaskId:56)
  Loading project references... (TaskId:56)
  Loading project files... (TaskId:56)
  Building the project model and resolving object interdependencies... (TaskId:56)
  Validating the project model... (TaskId:56)
  Writing model to P:<snip>\obj\Debug\Model.xml... (TaskId:56)
Done executing task "SqlBuildTask". (TaskId:56)

最佳答案

我对大型SSDT项目和TFS MSBUILD参数进行了以下更改,这些更改使通过TFS构建定义的构建时间达到了可以解释的水平:

1)将/p:CmdLineInMemoryStorage = TRUE添加到MSBUILD参数

tfs - 与VS 2013相比,使用MSBuild构建SSDT项目的速度要慢得多-LMLPHP

这大大减少了我们的构建时间。通过添加此选项,我们的构建定义从40分钟增加到16分钟。 (时间是删除重复引用的时间)

2)删除了.sqlproj文件中的所有重复引用

随着时间的流逝,.sqlproj文件成功引用了2到3次某些文件。我们有大约40个重复的引用。几乎可以肯定,这是由于我们许多分支机构之间的合并问题所致。 Visual Studio对此并没有提示,并且可以完美地构建,但是这些复制对我们在TFS中的构建时间产生了很大的影响,当然TFS使用MSBUILD。

在sqlproj文件中查找重复引用

这是我用来在sqlproj文件中查找重复项的powershell脚本(将 $ root 更改为指向包含.sqlproj文件的文件夹):

[Reflection.Assembly]::LoadWithPartialName("System.Xml.Linq") | Out-Null

$root = "C:\TFS"

$sqlprojFiles = Get-ChildItem -Path $root -Filter "*.sqlproj" -Recurse
$numFilesChecked=0

foreach ($f in $sqlprojFiles)
{
    $numFilesChecked++
    $fullName = $f.FullName

    $xml = [System.Xml.Linq.XDocument]::Load($fullName)
    $ns = $xml.Root.Name.Namespace;

    $itemGroups = $xml.Descendants() | Where-Object { $_.Parent.Name -eq $ns + "ItemGroup" };

    $dict = @{}
    $itemGroups.Attributes() | Where-Object { $_.Name -eq "Include"} `
        | % { if ($dict.ContainsKey($_.Value)) {$dict[$_.Value]++} else {$dict.Add($_.Value,1)} }

    $duplicates = $dict.Keys | Where-Object { $dict[$_] -gt 1}

    $fullName

    if ($duplicates.Count -gt 0)
    {
        Write-Output "--------------------------------------------------------"
        $duplicates | % {$_+", "+$dict[$_]}
    }
    else
    {
        Write-Output "No duplicates found"
    }
}

"Files checked: $numFilesChecked"

我使用此输出以文本方式手动编辑.sqlproj文件(即,在VS中先“卸载项目”,然后再“编辑.sqlproj”)

建立时间差异解释

既然我们的大型sqlproj在构建服务器上构建了9分钟,我认为可以解释VS和MSBuild之间的构建时间差异。

有人告诉我VS利用了命令行中MSBuild未使用的,关于SSDT项目的预编译信息。我无法证实这一点,而且在VS的“/verbosity:diagnostic”输出中,我当然也没有看到任何证据(我可能已经错过了)。但是,在VS完成对项目的分析之后,需要花费2分钟在VS 中构建大型项目,这表明它在构建过程中使用了缓存的信息。 VS需要花费几分钟才能完成对大型项目的分析。

现在,MSBuild构建时间(无论是从命令行还是从TFS构建定义)都需要9分钟的时间。几乎可以肯定,这7分钟是由MSBuild进程在每次构建时分析项目所占用的-VS似乎执行了一次(或至少定期执行),然后在构建时利用了缓存的信息。

09-26 20:09
查看更多