Roslyn compiled assembly performance: not as fast as the originally delivered version of Roslyn

What I do in one sentence

Checking the Update-1 branch from the Roslyn github repository , creating csc.exe, and compiling a random solution using csc. The exe version I just built.

Expected Result

I expect the performance to be comparable to the original version of Roslyn, which was sent with the update VS 2015 Update 1, located on the path: C:\Program Files (x86)\MSBuild\14.0\Bin

Actual result

The build performance of the Roslyn version that I built is significantly worse than the original. In the solution I used in my tests: about 30 seconds versus 65 seconds.

My procedure in more detail

  • Cloned https://github.com/dotnet/roslyn.git and checked for branch-1 update
  • Built by Roslyn using the Release configuration (for both platforms, as well as for the Mixed Configuration , and for x64 ).
  • To compile a test solution, I changed all the project files to use a specific location for the csc path:

    <CscToolPath>C:\Path\To\Output\Location\Of\Roslyn\Binaries\</CscToolPath>

  • For testing purposes, I am creating a test solution from the command line with

    MSBuild.exe /t:Rebuild /m:1 /verbosity:m MySolutionName.sln

  • I'm also doing a cleanup now:

    MSBuild.exe /t:Clean /m:1 /verbosity:m MySolutionName.sln

  • To test the original compiler that ships with VS 2015 Update 1, I change the configuration in the project files to:

    <CscToolPath>C:\Program Files (x86)\MSBuild\14.0\Bin\</CscToolPath>

Questions

  • What can I do to achieve similar performance with my self-compiled version of Roslyn, for example, with the originally sent Roslyn DLLs?
  • Are there any other things (for example, optimization, etc.) when building Roslin himself?
+8
msbuild roslyn
source share
2 answers

The biggest difference is that the official compiler installed by Visual Studio in NGEN is compiled as part of the installation.

However, even if you are NGEN, you will not get exactly equivalent results, because Microsoft has profiled training data to support partial NGEN in order to get a good balance between binary size and JIT time, which is not part of the public repo (similar to signing with the official secret Microsoft key).

+6
source share

In addition to the Kevin Answer, which is completely correct, here are some more details about signing / NGEN compiling Roslyn binaries, as this may be interesting to other people.

  • For NGEN to compile binaries, they must have a strong name, which means they must be signed
  • Typically, Roslyn binaries are delayed with a Microsoft private key, as Kevin pointed out.
  • Therefore, we must use our own key pair to sign
  • The corresponding configuration can be found in the Roslyn repository in the file build \ Targets \ VSL.Imports.targets
  • For testing purposes, we can then replace this section:
 <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 Keys\35MSSharedLib1024.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> 

with for example this:

 <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> 
  • ... using your own key file, public key, and public key token.
  • The key file can be created inside Visual Studio or using the sn.exe tool.
  • sn.exe can also be used to export the public key, as well as to extract the public key token (for example, from an assembly that you can verify with the key)
  • Then NGEN can be called like this:

    ngen.exe install "C:\path\to\Roslyn\Release\csc.exe"

(for example, located in C:\Windows\Microsoft.NET\Framework64\v4.0.30319\ngen.exe )

+1
source share

All Articles