aka*_*lou 7 java performance garbage-collection premature-optimization java-stream
网上有一些文章提到了使用Stream
-s 而不是旧的loop
-s 的一些缺点:
But is there any impact from the GC perspective? As I assume (is it correct?) that every stream call creates some short-lived objects underneath. If the particular code fragment which uses streams is called frequently by the underlying system could it cause eventually some performance issue from the GC perspective or put extra pressure on GC? Or the impact is minimal and could be ignored most of the time?
Are there any articles covering this more in detail?
公平地说,当霍尔格已经通过他的答案将主要思想联系起来时,给出答案是非常复杂的;我仍然会尝试。
GC 上的额外压力- 可能是。执行 GC 周期需要额外的时间 - 很可能不会。可以忽略吗?我想说完全可以。最后,您关心的是GC
- 只需很少的时间即可回收大量空间,最好是通过超小型的世界静止事件。
让我们谈谈 GC 主要两个阶段的潜在开销:标记和疏散/重新分配 (Shenandoah/ZGC)。第一mark
阶段,GC
找出什么是垃圾(通过实际识别什么是活的)。
如果 Stream 内部创建的对象不可访问,则永远不会扫描它们(此处为零开销),如果可访问,则扫描它们将非常快。故事的另一面是:当您创建一个对象并可能在标记阶段运行时GC
触摸它时,LoadBarrier 的慢速路径(在 的情况下)将处于活动状态。我认为这将增加该特定阶段的总时间以及队列中的一些空间。Aleksey Shipilev 在一次演讲中表示,他试图测量执行单个屏障的开销,但未能成功,因此他进行了测量,时间约为数十。我不知道 ZGC 的具体细节,但 LoadBarrier 也在那里。Shenandoah
ns
GC
SATB
3
ns
要点是,这个标记阶段是在应用程序运行时以并发方式完成的,因此您的应用程序仍然可以完美运行。即使某些 GC 代码会被触发去做一些特定的工作(负载屏障),它也会非常快并且对您来说完全透明。
第二阶段是“压缩”,即为未来的分配腾出空间。GC 的作用是将活动对象从垃圾最多的区域(Shenandoah
当然)移动到空的区域。但仅限于有生命的物体。因此,如果某个区域有 100 个对象,并且只有 1 个对象处于活动状态,则只有 1 个对象会被移动,那么整个区域将被标记为空闲。因此,如果 Stream 实现仅生成垃圾(即:当前不存在),那么它对于 GC 来说是“免费午餐”,它甚至不知道它的存在。
这里更好的情况是这个阶段仍然是同时完成的。为了保持“并发”活跃,您需要知道 GC 周期从开始到结束分配了多少内存。这个数量是为了让 GC 满意而需要在 java 进程之上拥有的最小“额外”空间。
总的来说,你看到的是一个非常微小的影响;如果有的话。
归档时间: |
|
查看次数: |
755 次 |
最近记录: |