Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the overhead of a data-less type?

I'm not wanting to start a flame war on micro-optimisation, but I am curious about something.

What's the overhead in terms of memory and performance of creating instances of a type that has no intrinsic data?

For example, a simple class that implements IComparer<T> may contain only a Compare method, and no properties or fields.

class FooComprarer : IComparer<Foo>
{
    public int Compare (Foo x, Foo y) 
    {
        // blah, blah
    }
}

Typical example code I've seen just calls new FooComparer(), wherever one of these is needed.

I can't imagine the instantiation cost here is very much at all, but I'm interested to know what it actually is. And how would it compare to, say, a static factory class that maintains a dictionary of types to comparers so that one comparer instance can be used everywhere it's needed.

like image 720
Andrew Cooper Avatar asked Jun 27 '11 23:06

Andrew Cooper


3 Answers

There is some overhead, but it's probably negligible compared to what you are going to use the comparer for.

On both a 32-bit and a 64-bit system that instance will use 16 bytes of heap space. The overhead is two pointers, which use 8 bytes on a 32-bit system and 16 bytes on a 64-bit system. However, the memory manager in the 32-bit system can't allocate blocks smaller than 16 bytes, so there will be 8 unused bytes in the block.

If you reuse those comparers a lot, you might consider to keep them around. However, you should also consider that short lived objects causes much less strain on the memory management than long lived objects, so you have to reuse the comparers a lot for it to be worth it to keep them alive.

like image 69
Guffa Avatar answered Oct 17 '22 15:10

Guffa


At minimum, a class object will still have a pointer to its type information and some housekeeping information even if it has no data members.

According to http://www.simple-talk.com/dotnet/.net-framework/object-overhead-the-hidden-.net-memory--allocation-cost/:

On a 32-bit system, every object has an 8 byte header [...] On 64-bit systems, the situation is worse. The object header is increased to 16 bytes.

like image 26
Tony the Pony Avatar answered Oct 17 '22 13:10

Tony the Pony


This is only tangentially related to your question but if you use C# 3.0 or higher you can use this pattern:

public class AdhocComparer<T> : IComparer
{
    Func<T, T, int> comparer;

    AdhocComparer(Func<T, T, int> comparer)
    {

        this.comparer = comparer;

    }

    public int Compare (Foo x, Foo y) 
    {
        return comparer(x, y);
    }

}

And use like so:

var fooComparer = new AdhocComparer<Foo>( (x, y) => /* do stuff */);

This way you don't have to create a class for each kind of IComparer you need.

like image 2
Rodrick Chapman Avatar answered Oct 17 '22 14:10

Rodrick Chapman