无数据类型的开销是多少?

时间:2011-06-27 23:33:47

标签: c# .net class overhead

我不想在微优化方面展开激烈的战争,但我对某些事感到好奇。

创建没有内部数据的类型的实例的内存和性能开销是多少?

例如,实现IComparer<T>的简单类可能只包含Compare方法,并且不包含任何属性或字段。

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

我见过的典型示例代码只需调用new FooComparer(),无论何处需要其中一个。

我无法想象这里的实例化成本是多少,但我很想知道它实际上是什么。如何比较一个静态工厂类来维护比较器的类型字典,以便可以在任何需要的地方使用一个比较器实例。

3 个答案:

答案 0 :(得分:13)

有一些开销,但与使用比较器相比,它可能是微不足道的。

在32位和64位系统上,该实例将使用16个字节的堆空间。开销是两个指针,在32位系统上使用8个字节,在64位系统上使用16个字节。但是,32位系统中的内存管理器不能分配小于16字节的块,因此块中将有8个未使用的字节。

如果您经常重复使用这些比较器,您可能会考虑保留它们。但是,您还应该考虑到短寿命对象对内存管理的压力比长寿命对象小得多,因此您必须重复使用比较器才能使它们保持活力。

答案 1 :(得分:2)

至少,类对象仍然会有一个指向其类型信息和一些内务处理信息的指针,即使它没有数据成员。

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

  

在32位系统上,每个对象都有一个8字节的标头[...]在64位系统上,情况更糟。对象标头增加到16个字节。

答案 2 :(得分:2)

这只与您的问题相关,但如果您使用C#3.0或更高版本,则可以使用此模式:

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);
    }

}

并像这样使用:

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

这样您就不必为每种所需的IComparer创建一个类。