【问题标题】:Why is Queue.poll faster than Iteration? (java.util.concurrent.ConcurrentLinkedQueue)为什么 Queue.poll 比 Iteration 快? (java.util.concurrent.ConcurrentLinkedQueue)
【发布时间】:2013-09-20 17:59:33
【问题描述】:

我有一段代码可以从队列中获取所有元素。之后我不关心队列的状态,我可以保证在我从中删除元素时不会修改队列。

我最初使用迭代器来拉取元素,因为我认为它会比轮询元素更快...

但我进行了以下测试:

ConcurrentLinkedQueue<Object> queue = new ConcurrentLinkedQueue<>();
for (int i=0; i < 1000000; i++)
    queue.add(new Object());

LinkedList<Object> list = new LinkedList<>();
long start = System.currentTimeMillis();
for (Object object: queue)
    list.add(object);
long time1 = System.currentTimeMillis() - start;

list = new LinkedList<>(); 
start = System.currentTimeMillis();
Object object;
while ((object = queue.poll()) != null)
    list.add(object);
long time2 = System.currentTimeMillis() - start;

System.out.println(time1 + " " + time2);

我得到以下输出(平均超过 100 次运行)

1169 46

我的问题是:为什么轮询比迭代更快?这对我来说完全不直观,因为 poll 将不得不修改队列,而 iterate 只需要查看状态。

edit --- 格雷是对的

我在一个循环中运行它并得到了输出(应该首先这样做)

1180 46
1422 25
287 32
14 26
226 26
236 25
12 26
14 25
13 25
13 26
13 25
268 25
13 25
14 176
13 26
13 26
13 25
13 25
13 26
13 24
13 26
13 25
...

【问题讨论】:

  • 猜猜看?在存在并发的情况下,迭代更加棘手。
  • 您是否尝试过多次运行上述代码。在实际读取值之前?这允许热点编译代码。差距似乎太大了。我跑了 10 次,结果都不同。
  • 重复运行代码。最终迭代器获胜。并且 toArray 可能更快。

标签: java concurrency queue


【解决方案1】:

我的问题是:为什么轮询比迭代更快?这对我来说完全不直观,因为 poll 将不得不修改队列,而 iterate 只需要查看状态。

正如@csoroiu 指出的那样,这似乎是一个热点编译器问题。鉴于 Java 的工作原理,在开始执行此类计时调用之前“预热”应用程序非常重要。

如果我在一个方法中运行你的测试 100 次,我最初看到由于 GC 开销和其他 JVM 魔法而导致的性能大不相同。但是,在添加一些.clear() 方法和方法末尾的System.gc() 之后,性能数字与迭代器获胜更加一致:

108 143
89 152
83 148
78 140
79 153
90 155
...

有关更多详细信息,请在此处查看 Peter 的回答:CPU execution time in Java

有关如何正确进行此类微基准测试的大量信息,请参阅此详尽答案:How do I write a correct micro-benchmark in Java?

【讨论】:

  • 有趣的是,迭代比轮询需要更多的预热
  • 不,@nikdeapen,性能周期会上下波动。迭代器在未来开始再次获胜。我对这些结果感到非常惊讶。
  • 好的。在向方法添加 .clear()System.gc() 调用后,数字稳定,迭代器始终领先 @nikdeapen。
  • @Gray 以获得更好的结果(如果您还没有这样做的话)将每个循环体放在一个单独的方法中。
  • 我在子方法@assylias 中看到了类似的结果。如果它有所作为,我会感到惊讶。您认为这些方法有助于火锅内联吗?
猜你喜欢
  • 2019-11-02
  • 1970-01-01
  • 2015-07-24
  • 1970-01-01
  • 2019-04-18
  • 2014-07-06
相关资源
最近更新 更多