Monday, January 17, 2005

.NET memory and performance improvement

Now that you have finished your .NET Application, the memory bogs you down?

Limiting memory usage of .NET applications is a requirement that often arises in programs that allocate and use large amounts of memory. The garbage collected environment that the CLR offers means that memory that is used to perform some calculation then discarded is not immediately collected once it is no longer needed, and application memory usage can become quite high in some situations. Rather than wait for all available memory to be exhausted before performing a full garbage collection, there are scenarios where preserving memory for other processes is a higher priority than the raw speed of the memory-intensive .NET application.

Well, there is a COM API RequestVirtualMemLimit to be called after overriding to prevent your application from hogging all the memory and waiting for the last instant for the GC to start freeing off memory. To the CLR, a failed RequestVirtualMemLimit call will appear the same as Windows running out of memory and returning a NULL pointer for a VirtualAlloc request. Rather than simply refusing to allocate any further memory, a gentler and more effective technique is to allow a small memory increase so exception objects can be successfully created, and an OutOfMemory exception can gracefully thrown and handled by managed code. If memory cannot be allocated for exception objects, the runtime will terminate without giving exception handlers a chance to execute, which will rarely be the desired behaviour.

Therefore, to place an effective cap on memory usage, an object implementing IGCHostControl needs to be provided to the runtime.

But the problem, is the "chicken and egg" problem. The ICorConfiguration interface, which is implemented by CorRuntimeHost, has a method called SetGCHostControl that allows an IGCHostControl-implementing object to be provided to the runtime. Unfortunately, it is not possible to retrieve an ICorConfiguration reference after the runtime has started. The QueryInterface logic of CorRuntimeHost fails throws an error when a request for ICorConfiguration is made, and the ICorRuntimeHost::GetConfiguration method, which returns a ICorConfiguration reference, fails when it is called post-startup. When certain hosting functionality is only available before the runtime is started, it is impossible to use the functionality from managed code. Managed code can never execute before the runtime starts, and if the functionality is required, as it is with the memory capping functions, the only option is to explicitly host the runtime using unmanaged code.
Read on at .
Thanks to the author for this insight into unmanaged code advantages in a managed world.

Looking forward to a better managed C++ in .NET 2.0

No comments: