代码之家  ›  专栏  ›  技术社区  ›  zproxy

规范化.NET泛型

  •  0
  • zproxy  · 技术社区  · 15 年前

    在重写程序集的过程中,如果我要指示编译器为每个泛型实例生成非能量类型,应用程序在代码中会变得更大,但性能相同吗?

    5 回复  |  直到 15 年前
        1
  •  2
  •   Scott Wisniewski    15 年前

    修改编译代码的大小(JIT之前或之后)可能会影响性能。

    例如,增加可执行代码的数量可能会导致额外的缓存未命中,或者占用更多的虚拟内存。这两种情况都会减慢程序的执行速度。

    此外,增加程序集中存在的命名类型的数量可能会降低运行时的速度。如果运行时必须检查更大的数据结构来解析类型名,那么解析类型名和执行JIT编译可能需要更长的时间。

    最后,如果它们是更多类型的JIT,那么clr最终会花费更多的时间生成代码。

    你需要做一些测试来确定,但我猜,做你所说的会有一个净的负面影响。

    不过,clr对于它生成的通用代码非常聪明。通用方法的不同引用类型实例最终会使用大多数相同的本机方法体,但需要加载类型标记的部分除外。但是,值类型实例最终会得到自己独特的本地方法体。

    这通常会提供良好的性能。它平衡了代码膨胀对性能的影响和额外装箱对性能的影响。

    对于您来说,在构建工作负载时,clr设计将导致非最佳性能,这当然是可能的。然而,这些病例在我看来是相当病态的。我敢打赌,对于大多数真正的代码,直接使用clr泛型可以获得更好的性能。

        2
  •  1
  •   Guffa    15 年前

    不,代码和性能实际上是相同的。

    编译器已经生成了特定的类。我不确定语言编译器做了多少工作,而JIT编译器做了多少工作,但最终结果实际上是相同的。

        3
  •  0
  •   Kevin Montrose    15 年前

    通过减少方法体中发生的强制转换和自动氧化(分别用于引用和值类型)操作的数量,泛型可以获得一些性能。

    MSDN article on generics .

    “无泛型”方法实现不应该从性能上获得任何好处,因为JIT将处理为您生成任何特定用例并积极缓存它们。

        4
  •  0
  •   Samuel Neff    15 年前

    与非泛型等价物相比,泛型提供了性能和运行时内存优势。例如,比较以下内容。

    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将包含对象[]的内部存储,其中每个元素都指向一个字节。因此,列表中这部分具有32位指针的理想内存是8*4+8=40字节。我说“理想”,因为实际上情况更糟,因为装箱的字节会有一些额外的开销,尽管我不知道具体有多少。

    相反,列表实现将包含byte[],它只需要一个指向数组的指针加上8个字节,总共12个字节的内存,而不需要装箱开销(无论是什么)。

    除了内存差异之外,还存在装箱/拆箱值的性能成本。

    对于引用类型来说,差异较小,但即使这样,从非泛型类型中提取数据时,也会不断地进行强制转换,从而造成成本损失。

    这些差异是真实存在的,但对大多数应用程序都会产生不可估量的影响。泛型的真正优点是编译时验证的可靠性更高,并且使用类型化值产生的代码更简单。

    在我看来,最好在适当和可能的时候使用仿制药。

    山姆

        5
  •  0
  •   rama-jka toti    15 年前

    这个问题很有道理。

    你唯一能保证的好处是更少的元数据或者更少的运行时解析,明显更少的键盘输入和更干燥。但是,这种情况与延迟C++编译器非常相似,BjARNE抱怨了很久。绝对不需要为指针容器生成膨胀。

    在任何情况下,C泛型都是非常糟糕的语言和运行时功能,可能会导致大量的头痛,而且没有接口几乎没有用处。无法进行值类型比较,这是一个非常糟糕的设计的明显例子,以及在翻译单元中大量使用(没有typedef)的情况。