【问题标题】:how can ArrayList of type Int32 can be bigger than List of type Int32 [duplicate]Int32 类型的 ArrayList 怎么能比 Int32 类型的 List 大 [重复]
【发布时间】:2014-12-25 01:47:02
【问题描述】:

我有一个作业,其中包括在创建泛型类型ArrayListList 的实例时解释以下结果。

ArrayList de Int32 = 280 ns ; 1.603.604 bytes   
List<Int32> = 59 ns ; 408.224 bytes 
ArrayList de String = 77 ns ; 408.224 bytes
List<String> = 74 ns ; 408.224 bytes

我花了相当多的时间试图弄清楚这一点,又花了很多时间试图在互联网上找到一些东西,但什么也没有。

提前致谢:)

【问题讨论】:

  • 我猜拳击会做出这种改变。发布代码,以便我们查看您的测试做了什么。
  • ArrayList 不是泛型类型。因此对于像 Int32 这样的值类型项,装箱将对运行时产生很大影响。
  • 我没有代码,唯一给出的就是输出...
  • 我真的不明白为什么有人反对这个问题。虽然它可能是重复的,但要求它的人很难知道它是重复的。甚至可以说它的不同之处足以不被视为与所提出问题的重复。

标签: c# .net generics


【解决方案1】:

我认为要求解决作业是不合适的。另一方面,我认为这项任务很愚蠢,因为您要么在某处阅读了有关差异以及 .NET 中泛型如何工作的信息,要么没有阅读,所以我想我还是会回答。

ArrayList 不是通用的,这意味着它包含一个对象数组。每个 int 都应该装在一个对象中,该对象增加了 12 个字节(我认为一个对象的开销是 12 个字节,但我可能会偏离几个字节)到实际的 4 个字节数据。这是将 int 包装在对象中的内存成本。进行包装和展开也有 CPU 时间成本。另一方面,List 或任何值类型都是专门的。这意味着 CLR 会为 int 生成一个特殊版本的列表。内部数组是一个 int 数组而不是对象数组,因此不会为数据丢失额外的内存。由于不执行装箱和拆箱,因此时间也有所改善。请注意,额外的对象会对 GC 施加压力,GC 必须在某个时候收集它们。

对于字符串没有惩罚,因为字符串是引用类型,所以它们的工作方式基本上与对象相同。它们已经包含 12 个字节的开销。强制转换时检查类型可能会产生一些 CPU 开销,但不会执行昂贵的装箱。这就是为什么泛型列表和 ArrayList 在性能和内存方面没有显着差异的原因

另外值得注意的是,这种方法并不是泛型在所有语言中的工作方式。例如,Java 就完全不同,因此如果您使用某些非 .NET 技术,请务必检查您的知识是否适用。

【讨论】:

  • 感谢您的回答,这个作业真的很混乱...
  • 在 64 位系统中,对象包装器应占用 16 个字节(类型指针为 8,指向System.Object,同步块指针为 8)。添加整数的 32 位。将数组的指针添加到装箱的 int。那是 28 个字节。因此,List&lt;int&gt; 每个整数需要 4 个字节,而ArrayList 需要 28 个字节。
  • @dcastro 似乎测试是在 32 位上进行的,因为 ArrayList 版本只占用了 4 倍的空间。
  • @Stilgar 是的,在 32 位系统上,一个装箱的 int 加上它的指针将占用 16 个字节(4 个用于类型指针,4 个用于同步块指针,4 个用于实际 int,4 个用于指针到装箱的 int),它是未装箱整数的 4 倍。
猜你喜欢
  • 2017-08-18
  • 2011-04-19
  • 2020-08-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-23
  • 2013-07-30
  • 1970-01-01
相关资源
最近更新 更多