Patrick Smacchia [MVP C#]

Sponsors

The Lounge

Advertisement

Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
Mono.Cecil vs. System.Reflection

 

Mono.Cecil is an open source framework, part of the Mono project, that reads .NET assemblies, but also that writes .NET assemblies. It is developed by Jean Baptiste Evain that now works full-time on the Mono project.


System.Reflection is a great framework because it is the .NET core base of several good practices that revolve around the Dynamic / Plug-In / Dependency Injection / Late-Binding kind of patterns
. These patterns currently represent a successful trend in the .NET community and you can convince yourself by having a glance at the List of .NET Dependency Injection Containers framework recently done by Scott Hanselman.


The object of the current post is to explain that System.Reflection must not be used to do something else than Late-Binding like code. Especially, System.Reflection should not be used to do any kind of code analysis. We (the NDepend
team) learnt this lesson the hard way after more than 3 years of hard-core work with System.Reflection. Hopefully we refactored our code that does static analysis and it is now (since NDepend v2.7) entirely based on Mono.Cecil. We are now plainly satisfied with this integration (btw, there is no licensing issue in using any code from Mono in a commercial or proprietary application).


So what's wrong with System.Reflection? It actually comes from its primary intention of doing Late-Binding things. As a result it can't consider code as just raw data. And this leads to many limitations such as:

  • At any time, browsing the code of an assembly loaded with Reflection might trigger a Code Access Security (CAS) exception because the data you’re playing with are still considered as code.
  • It has poor performance (I suspect that CAS security checks plays a major role in this perf issue).
  • It consumes a lot of memory (here also I suspect that it is because the CLR considers data as code) and it is hard to release this memory once you went through all the code of an assembly
  • You cannot load 2 different versions of an assembly inside an AppDomain (at least not intentionally as I explained here).
  • As a result of the previous limitation you cannot load a Microsoft assembly that has a different version than the current CLR version (for example, you cannot analyze mscorlib v1.1 from System.Reflection in mscorlib v2.0).


You can also read this great article from Joel Pobar Dodge Common Performance Pitfalls to Craft Speedy Applications if you want more understanding on how Reflection relies internally on cache that makes memory grow and some benchmark in the average performance of Reflection in general. Since .NET v2, System.Reflection supports a kind of read-only mode but as a heavy user of this feature I came to the conclusion that most of problems persist with this mode.

 

Another problem is that System.Reflection suffers from severe limitations (bugs?!) if you try to analyze out of the beaten path assemblies, I mean, not classic AnyCPU C# or VB.NET assemblies. For example:
      

  • It tosses many unexpected exceptions when it comes to tricky scenario where the assemblies analyzed contain static cctor or complex custom attributes.
  • It doesn't cop well with complex C++/CLI assemblies (that often don't respect the CLI) and this often leads to unexpected exceptions.
  • It doesn't cop well with not AnyCPU assemblies (i.e compile option 32/64bits) and here also, this often leads to unexpected exceptions.



Finally System.Reflection suffers from some others by-design limitations because:

  • It doesn't parse IL.
  • It doesn’t do the distinction about TypeRef and TypeDef as Jm Stall explains here. It means that you will get some UnresolvedException when you try to get information about a code element that is referencing some code elements in some assemblies not currently loaded in the current AppDomain.
  • It doesn't know about TypeSpec as Jm Stall explains here. It means that there will always be some tricky case such as a {ref List<U>*} typed parameter where Reflection won't do distinction between 2 overloads of a methods.


This post sounds as a bashing of System.Reflection but it is not. This framework is central to implement late-binding scenarios and personally I had a lot of fun with it. Also, IMHO Microsoft engineers did an awesome job at making sure that method calls and object instantiations thought reflection comes with really high performance (as Ayende mentioned recently). See also this great article from Joe Duffy on CLR method call internals. And finally, Reflection (and especially Reflection.Emit) is central to the new dynamic language trend (DLR). Here what Jim Hugunin, creator of IronPython wrote on its blog: We began to take advantage of the great new features for dynamic languages already shipping in .NET 2.0 such as DynamicMethods, blindingly fast delegates and a new generics system that was seamlessly integrated with the existing reflection infrastructure.



But when it comes to code analysis, Mono.Cecil is definitely the best option I came across. The object model is pure and made me learn the CLI much better than any other sources. The performances are awesome and the support provided by Jb Evain is just perfect. These last months’s we reported several bugs and most of time the fix came within a few hours! As a result, we really have a high trust in Mono.Cecil and my personal feeling it shouldn't be far from bug-free. Also, I didn’t talk at all about the great ability of Cecil to tweak assembly IL (simple because I didn't need it yet) but you can have a look here to see this amazing feature in action.





Posted 03-18-2008 11:36 AM by Patrick Smacchia

[Advertisement]

Comments

Lex Y. Li wrote re: Mono.Cecil vs. System.Reflection
on 03-18-2008 8:45 AM

Wonderful post

Dew Drop - March 18, 2008 | Alvin Ashcraft's Morning Dew wrote Dew Drop - March 18, 2008 | Alvin Ashcraft's Morning Dew
on 03-18-2008 9:57 AM

Pingback from  Dew Drop - March 18, 2008 | Alvin Ashcraft's Morning Dew

Peter Ritchie wrote re: Mono.Cecil vs. System.Reflection
on 03-18-2008 10:50 AM

Very interesting, thanks!

Dimitar E. Dimitrov wrote re: Mono.Cecil vs. System.Reflection
on 03-18-2008 10:53 AM

Mono.Cecil is something completely different than System.Reflection, but can be compared with the FxCop Framework after which it was modelled.

Jb Evain wrote re: Mono.Cecil vs. System.Reflection
on 03-18-2008 12:15 PM

Cecil has not been modeled from the FxCop underlying framework (something called CCI). I took inspiration from the great API that Reflector provides though.

Bruce Markham wrote re: Mono.Cecil vs. System.Reflection
on 03-18-2008 12:17 PM

I'm from the SharpOS project (http://www.sharpos.org/) - and we use Cecil to power our 100% C# AOT compiler, which we use to AOT our kernel (and later we will be using it as our JIT).

Cecil performs very well, and the API is considerably easy to navigate, with no steep learning curve.

We could have never pulled it off with System.Reflection

Seb Andreo wrote re: Mono.Cecil vs. System.Reflection
on 03-19-2008 4:27 AM

With the NDepend 2.7 we can analyze our ~9 million IL instructions code base with out any issues and with  a performance benfit about factor 3 !!!!

Thanks to Cecil and Jb for it hard work and thanks to NDepend Team :o) for this great tool.

hey guys continue the great job

cas wrote cas
on 03-19-2008 6:15 PM

Pingback from  cas

DotNetKicks.com wrote Mono.Cecil vs. System.Reflection
on 03-20-2008 1:09 AM

You've been kicked (a good thing) - Trackback from DotNetKicks.com

benchmark dodge wrote benchmark dodge
on 05-12-2008 2:22 PM

Pingback from  benchmark dodge

reflection wrote reflection
on 06-03-2008 1:26 PM

Pingback from  reflection

I hate Spaghetti (code) wrote Cecil mono – System.Reflection alternative
on 06-27-2008 2:27 PM

I&#39;m following mono for quite some time now and I&#39;m amazed of the wonderful job they are doing

on 08-21-2008 4:17 PM

Lexapro vs. celexa. Effects of lexapro. Lexapro and pregnancy. Lexapro.

Observations on the Evolution of Software Development « Critical Development wrote Observations on the Evolution of Software Development &laquo; Critical Development
on 09-18-2008 1:45 PM

Pingback from  Observations on the Evolution of Software Development &laquo; Critical Development

Derik Whittaker wrote re: Mono.Cecil vs. System.Reflection
on 10-30-2008 6:25 AM

Jason Bock has done a great intro screencast to Cecil over at DimeCasts.

You can check it out here www.dimecasts.net/.../59

Patrick Smacchia [MVP C#] wrote Lessons learned from a real-world focus on performance
on 12-01-2008 4:32 AM

I am glad to announce that we just released a new version of NDepend where the analysis phase duration

Community Blogs wrote Lessons learned from a real-world focus on performance
on 12-01-2008 4:55 AM

I am glad to announce that we just released a new version of NDepend where the analysis phase duration

Lessons learned from a real-world focus on performance - taccato! trend tracker, cool hunting, new business ideas wrote Lessons learned from a real-world focus on performance - taccato! trend tracker, cool hunting, new business ideas
on 12-02-2008 10:16 AM

Pingback from  Lessons learned from a real-world focus on performance - taccato! trend tracker, cool hunting, new business ideas

Lessons learned from a real-world focus on performance - taccato! trend tracker, cool hunting, new business ideas wrote Lessons learned from a real-world focus on performance - taccato! trend tracker, cool hunting, new business ideas
on 12-03-2008 11:03 AM

Pingback from  Lessons learned from a real-world focus on performance - taccato! trend tracker, cool hunting, new business ideas

Lessons learned from a real-world focus on performance - taccato! trend tracker, cool hunting, new business ideas wrote Lessons learned from a real-world focus on performance - taccato! trend tracker, cool hunting, new business ideas
on 12-04-2008 11:09 AM

Pingback from  Lessons learned from a real-world focus on performance - taccato! trend tracker, cool hunting, new business ideas

Patrick Smacchia [MVP C#] wrote My 100th blog post: Top 5 development practices you should care for
on 03-25-2009 3:49 AM

This is a modest number but I am happy to have reached it, especially taking account that I spend weekly

Community Blogs wrote My 100th blog post: Top 5 development practices you should care for
on 03-25-2009 3:59 AM

This is a modest number but I am happy to have reached it, especially taking account that I spend weekly

Patrick Smacchia [MVP C#] wrote The Microsoft project CCI (Common Compiler Infrastructure) goes Open Source
on 04-15-2009 6:39 PM

Download it on CodePlex here . CCI can read/write metadata contained inside .NET assemblies. My guess

Add a Comment

(required)  
(optional)
(required)  
Remember Me?