我注意到我们的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参数
这大大减少了我们的构建时间。通过添加此选项,我们的构建定义从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似乎执行了一次(或至少定期执行),然后在构建时利用了缓存的信息。