如果我要指示编译器为每个通用实例生成非泛型类型,那么在重写程序集时,应用程序会在代码中变得更大但性能是否相同?
答案 0 :(得分:2)
在JIT之前或之后修改已编译代码的大小会对性能产生影响。
例如,增加可执行代码的数量可能会导致额外的缓存未命中,或者耗尽更多的虚拟内存。这两种情况都会减慢程序的执行速度。
此外,增加程序集中存在的命名类型数可能会降低运行时间。如果运行时必须检查更大的数据结构以解析类型名称,那么解析类型名称和执行JIT编译可能需要更长的时间。
最后,如果他们的JIT类型更多,那么CLR最终可能会花费更多的时间来生成代码。
你需要运行测试才能确定,但我的猜测是,你正在谈论的事情会产生净负效应。
CLR对它生成的通用代码非常聪明。泛型方法的不同引用类型实例最终使用大多数相同的本机方法体,除了需要加载类型令牌的部分。但是,值类型实例最终会获得自己独特的本机方法体。
这通常提供良好的性能。它平衡了代码膨胀对额外拳击的性能影响的性能影响。
您当然有可能构建CLR设计会导致非最佳性能的工作负载。然而,这些案件对我来说似乎很病态。我愿意用大多数真实代码打赌,只需直接使用CLR泛型就可以获得更好的性能。
答案 1 :(得分:1)
不,代码和性能几乎相同。
编译器已经生成了特定的类。我不确定语言编译器完成了多少工作以及JIT编译器完成了多少工作,但最终结果几乎是一样的。
答案 2 :(得分:0)
泛型可以通过减少演员阵容数量来获得一些表现。自动装箱(分别用于参考和值类型)在方法体中发生的操作。
“Generic-less”方法实现不应该为您带来任何性能,因为JIT将处理为您生成任何特定用例并积极地缓存它们。
答案 3 :(得分:0)
与非通用等价物相比,泛型提供了性能和运行时内存优势。例如,比较以下内容。
ArrayList arrayList = new ArrayList(new Byte[] { 1, 2, 3, 4, 5, 6, 7, 8} );
VS
List<Byte> byteList = new List<Byte> { 1, 2, 3, 4, 5, 6, 7, 8 };
ArrayList将包含object []的内部存储,其中每个元素都指向一个字节。因此,具有32位指针的列表的这一部分的理想存储器是8 * 4 + 8 = 40字节。我说理想'因为它实际上更糟,因为盒装字节会有一些额外的开销,虽然我不确切知道多少。
List实现将包含byte [],它只需要一个指向数组的指针加上8个字节,总共12个字节的内存而没有装箱开销,无论是什么。
除了内存差异之外,还有装箱/取消装箱值的性能成本。
参考类型的差异较小,但即使在那里,当从非泛型类型中取出数据时,也会不断地进行投射成本。
这些差异是真实的,但会对大多数应用程序产生不可估量的影响。泛型的真正优势在于更高的编译时验证可靠性以及使用类型化值导致的更简单的代码。
在我看来,最好在适当和可能的情况下使用泛型。
萨姆
答案 4 :(得分:0)
这个问题是有道理的。
关于唯一保证的好处是运行时的元数据少或解析少,显然键盘输入和DRY更少。但是,这个案例非常类似于重新开发的C ++编译器以及Bjarne多年来抱怨的事情。绝对没有必要为指针容器生成膨胀..
在任何情况下,C#泛型都是一个非常差的语言和运行时功能,可能会引起很多麻烦,没有接口几乎没用。无法进行值类型比较是一个相当差的设计的明显例子,以及很多DRY在翻译单位等使用(没有typedef)。