Friday, January 21, 2005

.NET 2.0 Generics samples & Performance Comparison

One of the most awaited features of Microsoft .NET 2.0 is generics. Starting with VS 2005, C#, Managed C++, and VB will have CLR support for generics.

Generics promise to increase type safety, improve performance, reduce code duplication(code reuse) and eliminate unnessecary casts(boxing). The most obvious application of generics in the framework class library are the generic collections in the new System.Collections.Generic namespace.

While Generic types do have a similar syntax to C++ templates, they are instantiated at runtime as opposed to compile time (by Microsoft's C++ compiler), and they can be reflected on via meta-data. Also, in Generics, member access on the type paramater is verified based on the constraints placed on the type parameter; whereas, in templates, member access is verified on the type argument after instantiation. When the MS C++ compiler creates a separate type for every template specialization, that does not necessarily mean every type emits separate code. In fact, you'll find that through a feature called COMDAT folding, most templates share quite a bit of code. (Basically, the myth of code bloat for templates isn't true these days.) By having separate specializations of code at compile-time, the compiler has the ability to optimize each type individually, which includes inlining. If every instance of a function is inlined, the template code is thrown away by the linker resulting in less code. For these reasons, template code is generally much faster and leaner than an equivalent generic alternative.

C++ templates are a compile-time feature much like a macro preprocessor and are thus not a good solution for a highly dynamic language such as C#.

In .NET, for value types, generics is considerably faster, and for reference types, generics is typically comparable in performance—or faster.

Good Links:

Introducing Generics in the CLR

Generics Performance Results and a sample to test other collections

Generics Performance (CSharp)

The problem with .NET generics

A generic Set type for .NET

6 questions about generics.

Performance: Interfaces Vs. Inheritance (Abstract Base Classes) Vs. Generics

Thanks to the authors for the above links.

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