我不想在微优化方面展开激烈的战争,但我对某些事感到好奇。
创建没有内部数据的类型的实例的内存和性能开销是多少?
例如,实现IComparer<T>
的简单类可能只包含Compare
方法,并且不包含任何属性或字段。
class FooComprarer : IComparer<Foo>
{
public int Compare (Foo x, Foo y)
{
// blah, blah
}
}
我见过的典型示例代码只需调用new FooComparer()
,无论何处需要其中一个。
我无法想象这里的实例化成本是多少,但我很想知道它实际上是什么。如何比较一个静态工厂类来维护比较器的类型字典,以便可以在任何需要的地方使用一个比较器实例。
答案 0 :(得分:13)
有一些开销,但与使用比较器相比,它可能是微不足道的。
在32位和64位系统上,该实例将使用16个字节的堆空间。开销是两个指针,在32位系统上使用8个字节,在64位系统上使用16个字节。但是,32位系统中的内存管理器不能分配小于16字节的块,因此块中将有8个未使用的字节。
如果您经常重复使用这些比较器,您可能会考虑保留它们。但是,您还应该考虑到短寿命对象对内存管理的压力比长寿命对象小得多,因此您必须重复使用比较器才能使它们保持活力。
答案 1 :(得分:2)
至少,类对象仍然会有一个指向其类型信息和一些内务处理信息的指针,即使它没有数据成员。
在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创建一个类。