自编译的 Roslyn 构建性能:不如原始交付的 Roslyn 版本快
Self-compiled Roslyn build performance: Not as fast as originally shipped Roslyn version
一句话概括我在做什么
从 Roslyn github repository 检查分支 Update-1
,构建 csc.exe,并使用我自己构建的 csc.exe 版本编译一个随机解决方案。
预期结果
我希望性能与 VS 2015 Update 1 附带的原始 Roslyn 版本相当,位于路径:C:\Program Files (x86)\MSBuild.0\Bin
实际结果
与原始版本相比,我自己构建的 Roslyn 版本的构建性能明显更差。在我测试中使用的解决方案中:大约 30 秒对 65 秒。
我的程序更详细
- 克隆 https://github.com/dotnet/roslyn.git 并签出分支 update-1
- 使用
Release
配置构建 Roslyn(针对解决方案平台尝试了 Mixed Configuration
和 x64
。)
为了编译测试解决方案,我更改了所有项目文件以使用特定位置作为 csc 路径:
<CscToolPath>C:\Path\To\Output\Location\Of\Roslyn\Binaries\</CscToolPath>
出于测试目的,我使用
从命令行构建测试解决方案
MSBuild.exe /t:Rebuild /m:1 /verbosity:m MySolutionName.sln
我之前也在做清洁:
MSBuild.exe /t:Clean /m:1 /verbosity:m MySolutionName.sln
为了针对 VS 2015 Update 1 附带的原始编译器进行测试,我将项目文件中的配置更改为:
<CscToolPath>C:\Program Files (x86)\MSBuild.0\Bin\</CscToolPath>
问题
- 我可以做些什么来使用我自己编译的 Roslyn 版本实现类似的性能,就像最初提供的 Roslyn dll 一样?
- 在构建 Roslyn 本身时是否需要考虑其他事项(如优化等)?
最大的区别是Visual Studio在NGEN中安装的官方编译器编译为安装的一部分。
然而,即使你是 NGEN,你也不会得到完全相同的结果,因为 Microsoft 有配置文件引导训练数据来支持部分 NGEN,以便在二进制大小和 JIT 时间之间取得良好的平衡,而这不是public 存储库的一部分(类似于使用官方 Microsoft 私钥签名)。
除了 Kevin 的回答完全正确之外,这里还有一些关于 signing/NGEN 编译 Roslyn 二进制文件的更多详细信息,因为这对其他人来说可能很有趣。
- 要让 NGEN 编译二进制文件,它们必须有一个强名称,这意味着它们必须被签名
- 通常情况下,Roslyn 二进制文件 delay-signed 带有 Microsoft 私钥,正如 Kevin 还指出的那样。
- 所以我们必须使用自己的密钥对进行签名
- 对应的配置可以在文件build\Targets\VSL.Imports.targets
中的Roslyn repo中找到
- 出于测试目的,我们可以替换此部分:
<Choose>
<When Condition="'$(SignAssembly)' == 'true'">
<Choose>
<!-- Shipping binaries in an "official" build are delay-signed with the MS key; later, the signing
system will finish the strong-name signing. -->
<When Condition="'$(NonShipping)' != 'true'">
<PropertyGroup>
<AssemblyOriginatorKeyFile>$(VSLToolsPath)\Strong Name KeysMSSharedLib1024.snk</AssemblyOriginatorKeyFile>
<DelaySign>true</DelaySign>
<PublicKey>0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9</PublicKey>
<PublicKeyToken>31BF3856AD364E35</PublicKeyToken>
</PropertyGroup>
</When>
<!-- Non-shipping binaries are simply signed with the Roslyn internal key. -->
<Otherwise>
<PropertyGroup>
<AssemblyOriginatorKeyFile>$(VSLToolsPath)\Strong Name Keys\RoslynInternalKey.Private.snk</AssemblyOriginatorKeyFile>
<DelaySign>false</DelaySign>
<PublicKey>$(RoslynInternalKey)</PublicKey>
<PublicKeyToken>fc793a00266884fb</PublicKeyToken>
</PropertyGroup>
</Otherwise>
</Choose>
</When>
</Choose>
例如,这个:
<Choose>
<When Condition="'$(SignAssembly)' == 'true'">
<PropertyGroup>
<AssemblyOriginatorKeyFile>C:\path\to\keyfile\TestKey.snk</AssemblyOriginatorKeyFile>
<DelaySign>false</DelaySign>
<PublicKey>0024000004800000940000000602000000240000525341310004000001000100B15B00E697DB995031A740A3E07A0B1DBE16AAEA61E615A013E0381B4D875F97F1792965D58810893F6D4B1C10CBD991FB8E9F1118D9C0C6F0EBCB50462FC25056E194667CB59822C18E9CB0C17DBC573291F05F7C87B51C48B377C9EEE12F6D5B331B235E5D6E3669737B210F7BE245A76B118C23EAD90FC392E4ED9F6CDFAB/PublicKey>
<PublicKeyToken>6E0B9EF75D28854E</PublicKeyToken>
</PropertyGroup>
</When>
</Choose>
- ...使用您的自己的密钥文件、public密钥以及public密钥令牌。
- 密钥文件可以在 Visual Studio 中或借助 sn.exe 工具创建。
sn.exe
也可用于导出 public 密钥以及提取 public 密钥令牌(例如,从一个程序集中,您可以 test-sign 使用键)
那么NGEN可以这样调用:
ngen.exe install "C:\path\to\Roslyn\Release\csc.exe"
(例如位于 C:\Windows\Microsoft.NET\Framework64\v4.0.30319\ngen.exe
)
一句话概括我在做什么
从 Roslyn github repository 检查分支 Update-1
,构建 csc.exe,并使用我自己构建的 csc.exe 版本编译一个随机解决方案。
预期结果
我希望性能与 VS 2015 Update 1 附带的原始 Roslyn 版本相当,位于路径:C:\Program Files (x86)\MSBuild.0\Bin
实际结果
与原始版本相比,我自己构建的 Roslyn 版本的构建性能明显更差。在我测试中使用的解决方案中:大约 30 秒对 65 秒。
我的程序更详细
- 克隆 https://github.com/dotnet/roslyn.git 并签出分支 update-1
- 使用
Release
配置构建 Roslyn(针对解决方案平台尝试了Mixed Configuration
和x64
。) 为了编译测试解决方案,我更改了所有项目文件以使用特定位置作为 csc 路径:
<CscToolPath>C:\Path\To\Output\Location\Of\Roslyn\Binaries\</CscToolPath>
出于测试目的,我使用
从命令行构建测试解决方案MSBuild.exe /t:Rebuild /m:1 /verbosity:m MySolutionName.sln
我之前也在做清洁:
MSBuild.exe /t:Clean /m:1 /verbosity:m MySolutionName.sln
为了针对 VS 2015 Update 1 附带的原始编译器进行测试,我将项目文件中的配置更改为:
<CscToolPath>C:\Program Files (x86)\MSBuild.0\Bin\</CscToolPath>
问题
- 我可以做些什么来使用我自己编译的 Roslyn 版本实现类似的性能,就像最初提供的 Roslyn dll 一样?
- 在构建 Roslyn 本身时是否需要考虑其他事项(如优化等)?
最大的区别是Visual Studio在NGEN中安装的官方编译器编译为安装的一部分。
然而,即使你是 NGEN,你也不会得到完全相同的结果,因为 Microsoft 有配置文件引导训练数据来支持部分 NGEN,以便在二进制大小和 JIT 时间之间取得良好的平衡,而这不是public 存储库的一部分(类似于使用官方 Microsoft 私钥签名)。
除了 Kevin 的回答完全正确之外,这里还有一些关于 signing/NGEN 编译 Roslyn 二进制文件的更多详细信息,因为这对其他人来说可能很有趣。
- 要让 NGEN 编译二进制文件,它们必须有一个强名称,这意味着它们必须被签名
- 通常情况下,Roslyn 二进制文件 delay-signed 带有 Microsoft 私钥,正如 Kevin 还指出的那样。
- 所以我们必须使用自己的密钥对进行签名
- 对应的配置可以在文件build\Targets\VSL.Imports.targets 中的Roslyn repo中找到
- 出于测试目的,我们可以替换此部分:
<Choose>
<When Condition="'$(SignAssembly)' == 'true'">
<Choose>
<!-- Shipping binaries in an "official" build are delay-signed with the MS key; later, the signing
system will finish the strong-name signing. -->
<When Condition="'$(NonShipping)' != 'true'">
<PropertyGroup>
<AssemblyOriginatorKeyFile>$(VSLToolsPath)\Strong Name KeysMSSharedLib1024.snk</AssemblyOriginatorKeyFile>
<DelaySign>true</DelaySign>
<PublicKey>0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9</PublicKey>
<PublicKeyToken>31BF3856AD364E35</PublicKeyToken>
</PropertyGroup>
</When>
<!-- Non-shipping binaries are simply signed with the Roslyn internal key. -->
<Otherwise>
<PropertyGroup>
<AssemblyOriginatorKeyFile>$(VSLToolsPath)\Strong Name Keys\RoslynInternalKey.Private.snk</AssemblyOriginatorKeyFile>
<DelaySign>false</DelaySign>
<PublicKey>$(RoslynInternalKey)</PublicKey>
<PublicKeyToken>fc793a00266884fb</PublicKeyToken>
</PropertyGroup>
</Otherwise>
</Choose>
</When>
</Choose>
例如,这个:
<Choose>
<When Condition="'$(SignAssembly)' == 'true'">
<PropertyGroup>
<AssemblyOriginatorKeyFile>C:\path\to\keyfile\TestKey.snk</AssemblyOriginatorKeyFile>
<DelaySign>false</DelaySign>
<PublicKey>0024000004800000940000000602000000240000525341310004000001000100B15B00E697DB995031A740A3E07A0B1DBE16AAEA61E615A013E0381B4D875F97F1792965D58810893F6D4B1C10CBD991FB8E9F1118D9C0C6F0EBCB50462FC25056E194667CB59822C18E9CB0C17DBC573291F05F7C87B51C48B377C9EEE12F6D5B331B235E5D6E3669737B210F7BE245A76B118C23EAD90FC392E4ED9F6CDFAB/PublicKey>
<PublicKeyToken>6E0B9EF75D28854E</PublicKeyToken>
</PropertyGroup>
</When>
</Choose>
- ...使用您的自己的密钥文件、public密钥以及public密钥令牌。
- 密钥文件可以在 Visual Studio 中或借助 sn.exe 工具创建。
sn.exe
也可用于导出 public 密钥以及提取 public 密钥令牌(例如,从一个程序集中,您可以 test-sign 使用键)那么NGEN可以这样调用:
ngen.exe install "C:\path\to\Roslyn\Release\csc.exe"
(例如位于 C:\Windows\Microsoft.NET\Framework64\v4.0.30319\ngen.exe
)