About Me

My photo
Northglenn, Colorado, United States
I'm primarily a BI Developer on the Microsoft stack. I do sometimes touch upon other Microsoft stacks ( web development, application development, and sql server development).

Tuesday, January 16, 2007

C# Leaking

I got this info from MSDN magazine Jan 2007 Vol 22 No 1 issue.

Leaking Unmanaged Heap Memory:

  • Interoperating with unmanaged code

  • Problem: "Using C-style DLLS that use P/Invoke and COM objects through COM interop. The Garbage Collector is unaware of unmanaged memory".

    Solution: "Step through the code and examine memory usage before and after the unmanaged call to verify that the memory is reclaimed."

  • Aborted Finalizers

  • Problem: "An objects finalizer does not get called and it contains code to clean up unmanaged memory allocated by the object".

    Solution: "In .Net 1.x the only solution was to tear down the process and start again. The .Net Framework 2.0 introduces critical finalizers, which indicate that a finalizer will be cleaning up unmanaged resources and must be given a chance to run during AppDomain teardown."

  • Dynamic Code Generation Leaks

  • Problem: "Sometimes code needs to be generated dynamically... dynamic assemly must be regenerated. The old assembly will no longer be used, but there is no way to evict it from memory."
    Solution: "Check if you are regenerat[ing] code". You could either "load the generated MSIL into a child AppDomain. The child AppDomain can be unloaded when the generated code changes and a new one spun up to host the updated MSIL." Or, in 2.0 you can use DynamicMethod.Invoke.

  • XmlSerializer Leaks

  • Problem: "XMLSerializer caches the temporary assemblies on a per-type basis" and when changing the root name within the XML by overloading the XMLSerializer constructor which doesn't cache.

    Solution: Use XMLRootAttribute instead.

Leaking Managed Heap Memory

  • Large Obect Heap Fragmentation

  • Problem: An object is 85,000 bytes or larger and allocated on the large object heap. "Unlike the rest of the managed heap, the Large Obect Heap is not compacted due to the cost of moving the large object. So as large objects are allocated, freed and cleanded up, gaps will appear." Which result in more memory usage then needed.

    Solution: Try examining "how the application uses memory and specifically the types of objects that are on the large object heap using tools like CLRProfiler". Try to reduce the reliance on the LOH.

  • Unneeded Rooted References

  • Problem/Solution: Forgetting to Null out rooted references, which prevents the GC from freeing up memory.

  • Midlife Crisis

  • Problem: "A midlife crisis [...] is the overuse of managed heap memory and excessive amounts of processor time spent in the GC". An object lives to Gen1 or Gen2 and dies shortly afterward.

    Solution: Beware of using finalizers in managed code. Use finalizers if there is a reference to unmanaged code. If using IDisposable, "implement the Dispose pattern to allow users of the object to clean up the resources and avoid finalization". Also don't hold onto objects before making a query to the database or a webservice.

Monday, January 08, 2007

.Net Framework Clarification on Stacks and Heaps

I was reading through January issue of MSDN on the article "Identify And Prevent Memory Leaks In Managed Code", where (James Kovacs) started discussing stacks and heaps. I and a couple of other co-workers where wondering about more details on what they do and why they are needed.

Stacks: "The stack is where local variables, method parameters, return values, and other temporary values are stored during the execution of an application. A stack is allocated on a per-thread basis and serves as a scratch area for the thread to perform its work. The GC [Garbage Collector] is not responsible for cleaning up the stack because the space on the stack reserved for a method call is automatically cleaned up when a method returns. Note, however, that the GC is aware of references to objects stored on the stack. When an object is instantiated in a method, its reference (a 32-bit or 64-bit integer depending on the platform) is kept on the stack, but the object it-self is stored on the managed heap and is collected by the garbage collector once the variable has gone out of scope."

Unmanaged Heap: "The unmanaged heap is used for runtime data structures, method tables, Microsoft intermediate language (MSIL), JITed code and so forth. Unmanaged code will allocate objects on the unmanaged heap or stack depending on how the object is instantiated. Managed code can allocate unmanaged heap memory directly by calling into unmanaged Win32 APIs or by instantiating COM objects. The CLR itself uses the unmanaged heap extensively for its data structures and code."

Managed Heap: "The managed heap is where managed objects are allocated and it is the domain of the garbage collector. The CLR uses a generational, compacting GC. The GC is generational in that it ages objects as they survive garbage collections; this is a performance enhancement. All versions of the .NET Framework have used three generations, Gen0, Gen1, and Gen2 (from youngest to oldest). The GC is compacting in that it relocates objects on the managed heap to eliminate holes and keep free ememory contiguous. Moving large objects is expensive and therefore the GC allocates them on a separate Large Object Heap, which does not compact."