Build/Test Issues

Not identical at IL-level

Started by Silvenga on 7,856 views

My team is currently running NCrunch on our projects - which includes the use of a grid server. Recently, we've found an odd warning that pops up on a single project (out of 24 right now) which can be found below:

NCrunch has detected that compiled assemblies produced by different machines in the grid are not identical at IL-level. This is usually caused by grid machines using different compiler versions.


Since we are running VS2013 (waiting patiently for funding to upgrade), but wanted to use C# 6.0, we've been using the nuget package `Microsoft.Net.Compilers`. This package creates targets to override the ToolPath for csc to use the included out-of-band compilers, enabling new C# versions under old VS instances. Hence, in theory, the grid server should be using the same exact csc compilers to output the same IL code.

With the inclusion of IL level detection, my team has seen a definite improvement in impact detection (which we use primarily due to our machine CPU bottlenecks), so I'm trying to avoid downgrading to Text level detection.
Hi, thanks for sharing this issue.

NCrunch's IL-level impact detection works by generating a sequence of hashes from the assembly built for each project. The detection has no knowledge of language or syntax, and works only using the generated IL codes from the assembly.

So all it really knows here is that the assembly generated on your grid node is different in structure to the one built on your workstation. A difference in the compiler used is a possibility that should be investigated.

One way to analyse this issue further is to use ildasm.exe to obtain an IL-dump of the assembly on both your workstation and your grid server. You can then compare these IL dumps using a diff tool to see how the assemblies are different. For example:

ildasm myassembly /out:myassembly.il

You can do this with both NCrunch generated assemblies (which can be found by right-clicking on the project and choosing advanced->browse to workspace), and for assemblies built yourself by running MSBuild or VS on your workstation or grid node.

Edited

This was fun. So I took your suggestions and compared the differences and confirmed that the compiled IL is exactly the same except for a constant added by the compiler, see below:

The following code is for our logger using NLog:

Logger.Log(ToNLogLevel(level))
      .Property("Type", objectType)
      .Property("ObjectId", objectId)
      .Property("Area", area)
      .Message(message)
      .Write();

The write function under NLog has the following signature:

public void Write([CallerMemberName] string callerMemberName = null, [CallerFilePath] string callerFilePath = null, [CallerLineNumber] int callerLineNumber = 0)

It appears that the compiler is inserting the file path in place of the CallerLineNumberAttribute. As the remote server is building in a different path, the resulting IL code will be different.

      IL_0078:  callvirt   instance class [NLog]NLog.Fluent.LogBuilder [NLog]NLog.Fluent.LogBuilder::Message(string)
      IL_007d:  ldstr      "Write"
      IL_0082:  ldstr      "C:\\NCrunch Grid Node\\1168\\1614\\src\\<snip>"
      + "<snip>"
      IL_0087:  ldc.i4.s   99
      IL_0089:  callvirt   instance void [NLog]NLog.Fluent.LogBuilder::Write(string,
                                                                             string,
                                                                             int32)
Would you be interested in trying the build below? It includes a fix targeted to address the above problem.

http://downloads.ncrunch.net/NCrunch_Console_3.3.0.1.msi
http://downloads.ncrunch.net/NCrunch_Console_3.3.0.1.zip
http://downloads.ncrunch.net/NCrunch_GridNodeServer_3.3.0.1.msi
http://downloads.ncrunch.net/NCrunch_GridNodeServer_3.3.0.1.zip
http://downloads.ncrunch.net/NCrunch_LicenseServer_3.3.0.1.zip
http://downloads.ncrunch.net/NCrunch_VS2008_3.3.0.1.msi
http://downloads.ncrunch.net/NCrunch_VS2010_3.3.0.1.msi
http://downloads.ncrunch.net/NCrunch_VS2010_3.3.0.1.zip
http://downloads.ncrunch.net/NCrunch_VS2012_3.3.0.1.msi
http://downloads.ncrunch.net/NCrunch_VS2012_3.3.0.1.zip
http://downloads.ncrunch.net/NCrunch_VS2013_3.3.0.1.msi
http://downloads.ncrunch.net/NCrunch_VS2013_3.3.0.1.zip
http://downloads.ncrunch.net/NCrunch_VS2015_3.3.0.1.msi
http://downloads.ncrunch.net/NCrunch_VS2015_3.3.0.1.zip
http://downloads.ncrunch.net/NCrunch_VS2017_3.3.0.1.msi
http://downloads.ncrunch.net/NCrunch_VS2017_3.3.0.1.zip
That was fast! I upgraded both the grid server and my local installation and it appears that the issue is still present. Below is a full diff of the two assemblies.

http://pastebin.com/bQzQKE67 (better formatting)
That's unfortunate. I'm having trouble viewing your paste, it seems to have been set to private. Is there any other way you can share it with me? Perhaps submitting it through the contact form?.
Remco wrote:That's unfortunate. I'm having trouble viewing your paste, it seems to have been set to private. Is there any other way you can share it with me? Perhaps submitting it through the contact form?.


Oops, miss clicked. It should now be visible.
Sorry for the time it's taken me to come back to you on this one. The fix turned out to be a bit more complicated than I had expected.

I'm expecting to have a new build out later this week (v3.3). This build will contain a revised version of the fix that has been more thoroughly tested against NLog itself.

Edited

Post a reply

Log in to reply.