Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Code analysis improvement

Static CA makes solution build mutch slower. In my case > 2x slower than without CA. We can disable it but that is bad decision to lose its power. So what can we do?

First lets see how CA works.

You build solution. At each project build after msbuild Compile target fxcopcmd.exe is called with paths to assemblies which should be analyzed. fxcopcmd. generates CA xml log which is used by VS (or maybe output stream). fxcopcmd.exe loads assemblies(fast) and analyzing its synchronously, so only one CPU is loaded and 3 (in my case) are doing nothing. Only after CA is finished the next project in project dependency chain is builded.

So the weak place in CA were we can improve it - to force it work in parallel to use all CPUs.

I see such solution

To make fake fxcopcmd.exe that will take parameters from MSBUILD, remember it and instantly report to msbuild that all is ok and there were no error(through CA xml.log, or succeeded file, or maybe stream..). So MSBUILD will build the next project and at that time we will call real fxcopcmd.exe with saved parameters... if MSBUILD will call fxcopcmd.exe on next project - we will call one more time fxcopcmd.exe... so there will be few processes which will load all CPU'S. After real fxcopcmd.exe will finished we can call our MSBUILD target which will call only CA target from microsoft.common.targtets with out compiling and our fake fxcopcmd.exe will instantly reporting results (CA is finished at that time and we have log) to MSBUILD-VS.

What do you think? Will this speed up CA? Why Microsoft didn't make such staff and use only one CPU in CA?

like image 725
Brans Ds Avatar asked Oct 04 '22 01:10

Brans Ds


1 Answers

I've once asked a similar question on Connect and got a reply directly from the team. At the ALM Summit in 2012 I discussed the topic and there were a number of reasons (in no particular order)

  • The Code Analysis engine will most likely be replaced once Project Roslyn integrates into the Visual Studio product. Roslyn will offer realtime analysis (like Resharper) and the ability to 'fix' issues found.
  • The engine is very CPU intensive and already uses multiple CPU's, so running multiple instances might not help you as much as you suspect. Also, fxcop can be very I/O intensive (loading assemblies, pdb's, and other files) which would only get worse when you load multiple instances at the same time.
  • The build engine needs access to the build output. For referencing, but also for other tasks. Therefore it needs to know that the files are no longer in use when a task finishes. For example, when you add a task that IlMerges a number of assemblies together which removes the old ones afterwards, it needs access to those files. Same goes for simple move/package/etc actions.
  • The ability to fail the build early when a code analysis issue (set to level=error) is found will not work, since you're only gathering the results at the very end. Possibly causing you to build everything, only to find out you can't use the end-result.

As you can see here in this MSDN forum post, Fxcop itself already uses multiple threads and (at least in the rules that shipped with 2010) there are a few issues with concurrency already that cause us to turn off concurrency for Fxcop in certain cases. If you want fxcop to use more (or fewer) threads, you can edit the fxcopcmd.exe.config file:

 <FxCopEngineSettings Version="1.32">
   <Engines>
     <Engine Name="Introspection" Enabled="True">
       <!-- Change this number to use more (or fewer) threads -->
       <Threading Count="1" />
       <EnableFlowAnalysis>True</EnableFlowAnalysis>
     </Engine>
   </Engines>
 </FxCopEngineSettings>

Though the forum post mentions Visual Studio 2008, I have applied this to fix issues with 2010 as well.

A much simplest way to make FxCop more efficient is to call it once after all projects have been compiled. This will cause it to only load all symbols and referenced assemblies once and will allow the engine to make maximum use of parallelism. There are some issues with this as well when you have a solution that mixes multiple target platforms and cpu's or when you want to use different .rules files for different projects.

Or you could do the same thing I do, which is to configure FxCop for your local solution, but not set it to run on each build. Then in Team Foundation Server Team Build (or any other build server you might use), override the configuration for FxCop to run "Always". That way you have no performance impact while building your local solution. It still allows you to run Code Analysis for your whole solution locally (from the Analyze menu item) and the automated build can guard you against checking in code with issues.

like image 158
jessehouwing Avatar answered Oct 13 '22 10:10

jessehouwing