Tonight we had the best turnout ever at the C# User Group. We had 27 people show up for the advanced topics of memory management and code dom. We really seem to be getting the word out about all of these meetings and lots of people are showing up.
First up to bat was Keith Rome who presented AppCenter Test to the group. He was demonstrating some memory and performance problems with a simple application that did some really horrible stuff with strings and integers (check Keith’s code to see why StringBuilder is not necessarily protection against bad coding). AppCenter Test was really easy to set up because he was able to simply record the input to his webpage. Then he opened the ACT tester and was ready to go. The reports that ACT spit out for us were really great, showing us graphs and charts of the results which were especially impressive when he compared multiple tests against each other. AppCenter Test is only available in Enterprise Architect editions of Visual Studio.
Following Keith, Mitch Harpur from MetaJunction showed us a 20 minute presentation of CodeDom. To begin with, you should know what the code dom is – the ability to write some code that actually writes other code (generated code). Code generation is very handy because common code (ex data access layers) can be easily generated. Once that kind of code is stable it will have less errors than code done by hand. Code gen also helps your code fit into templates and patterns. Code has some areas which are ideal candidates for code generation, but not every problem works with code generation. You’ll want to to look into the System.CodeDom and System.CodeDomGenerator namespaces. Mitch showed us an excellent example where he was able to generate a class with very little actual code. I tell you what, Mitch showed us that he is a very bright guy and I’m going to really have to work to find some real understanding of code generation. This seems like a really complex topic which is easy to get wrong.
Doug Turnure was our group’s pinch hitter – presenting memory management in C#. We started with a review of CS 101 and rapidly went into memory diagrams.
- What’s the difference between a class, an object, and a reference?
- What is a stack and what is the heap and where can you find the managed heap?
- We sat together and walked through a simple code example to see how .Net will load up a type structure and initialise variable on the stack and the heap.
- We talked about how the typestruct is internally a CoreInfoClassStruct – a vtable that points to code compiled by the JIT compiler and how once compiled that code is kept around and referenced directly by the vtable.
- We talked about the difference between static vs instance members of a class and how static methods are faster than instance methods.
- We talked about the difference between value types and reference types (ref types are objects that get GCed where value types are raw data and not objects).
- Structures in .Net are faster than structures but you can’t inherit from them and you can’t replace the default constructor. One of the reasons structures are faster is that they are placed directly on the stack and are not pointed to on the heap. Structures CAN have methods and act just like classes.
- We talked about coping or cloning objects. Shallow copy vs deep copy. Deep copy-cloning is easily done by serialising the object into memory and re-hydrating the object into a new ref.
- Boxing is basically copying a value type just like it’s a reference type. Boxing occurs when you assign a value type to a reference value (ex – storing structs in an ArrayList). Unboxing is when you assign a reference type to a value type. The important thing to remember here is that boxing data creates a copy of that data and so if you change that boxed data you are not changing the original copy – it is up to you to synchronise those changes
- Generics are objects where the type is defined later.
- Garbage collection – Memory on the heap is allocated for (small) objects contiguously (that means really quickly) until there isn’t enough space on the managed heap. When you run out of space, unused objects (objects that have been orphaned when their references were set to null) are cleared out. Objects that survive garbage collection (because they’re still in use) are promoted from Gen 0 to Gen 1. When all the space is taken by Gen 1 objects, the GC will attempt to clean out all the Gen 1 objects and promote all the survivors of Gen 1 to Gen 2. When all the memory on the heap is full of Gen 2 objects, you’re out of memory! Garbage collection can be invoked manually, but in 99% of situations the automatic GC is more than sufficient. Always try to use a try..finalise which helps clean up objects. Also, don’t override Finalise unless you can’t help it – that’s slow! IDisposable is great but means your client code has to call it. That means you should implement both IDisposable AND a Finalise to ensure you clean up your object. You should also include a SuppressFinalize method as well.
The net conclusion of this talk is that Doug can crush you with his brain. Do not mess with Doug! Plus he’s funny even though he can’t be trusted with a marker and a dry erase board.
— Matt Ranlett