【问题标题】:Java repeated object allocations perfomance impactJava 重复对象分配对性能的影响
【发布时间】:2017-01-01 23:59:06
【问题描述】:

为什么对于 big n,LinkedList 比常规数组慢 10 倍(没有新分配):

  Deque<Boolean> tail = new LinkedList<>();
  for (int i = 1; i <= n; i++) {
       tail.addFirst(true);
       tail.pollLast();
  }

我的第一个猜测是 gc 时间,但它只需要 3.5 秒中的 100 毫秒。 找出这背后原因的最佳方法是什么?

【问题讨论】:

  • 链表要求每增加一个元素就分配一个新节点。数组或ArrayList 不会,因为您将一次性分配大量插槽来保存元素。分配需要时间。
  • 你可以在这里找到你的答案。请看stackoverflow.com/questions/1589813/…

标签: java performance garbage-collection allocation


【解决方案1】:

找出这背后原因的最佳方法是什么?

有很多方法:

  1. 将您的示例转换为适当的基准并使用分析器运行它。然后看看时间都花在了哪里。

  2. 查看您正在调用的 LinkedList 方法的源代码。

  3. 检查 Javac 编译器为您的代码和 LinkedList 代码生成的字节码。

  4. 检查 JIT 编译器为您的代码和 LinkedList 代码生成的本机代码。

(我会让你自己去调查,因为我怀疑它会显示出什么特别出乎意料的东西。)


我的第一个猜测是 gc 时间,但它只需要 3.5 秒中的 100 毫秒。

很可能大部分时间都用于分配和初始化链表节点对象,以及其他列表方法的开销。

如果在构建列表时确实需要运行 GC,那么在 LinkedList 情况下的 GC 开销会比在数组情况下要大一些。但我怀疑实际发生的是 GC 实际上正在回收在代码加载和(可能)JIT 编译期间创建的对象。在列表/数组构建期间产生的实际可收集垃圾的数量应该为零......在这两种情况下。

您的基准测试方法也可能会扭曲结果。例如,我注意到您的 pollLast 电话没有做任何有用的事情......关于构建列表。另一个问题可能是您不允许 JVM 预热效果。

一般而言,您看到的 10 倍差异对应于 Java 列表与数组性能的“公认智慧”。如果您使用ArrayList 而不是LinkedList,则性能将更接近于裸阵列,尤其是如果您对ArrayList 容量进行了良好估计。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-06
    • 2018-04-29
    • 1970-01-01
    • 2018-07-01
    • 1970-01-01
    • 2017-06-12
    • 2015-12-03
    相关资源
    最近更新 更多