可选的< T>的GC开销为0.在Java中 [英] GC overhead of Optional<T> in Java

查看:61
本文介绍了可选的< T>的GC开销为0.在Java中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们都知道,用Java分配的每个对象都增加了以后的垃圾回收周期的权重,并且Optional<T>对象没有什么不同.我们经常使用这些对象来包装可为空的对象,这会导致代码更安全,但是要付出什么代价呢?

We all know that every object allocated in Java adds a weight into future garbage collection cycles, and Optional<T> objects are no different. We use these objects frequently to wrap nullable, which leads to safer code, but at what cost?

是否有人知道可选对象添加了什么样的附加GC压力而不是简单地返回空值,以及这对高通量系统的性能有什么样的影响?

Does anyone have information on what kind of additional GC pressure optional objects add vs. simply returning nulls and what kind of impact this has on performance in high-throughput systems?

推荐答案

我们都知道,用Java分配的每个对象都会在未来的垃圾回收周期中增加权重,……

We all know that every object allocated in Java adds a weight into future garbage collection cycles,…

这听起来像是一条没有人可以否认的声明,但让我们看一下垃圾收集器的实际工作,考虑现代JVM的常见实现以及分配的对象对它的影响,尤其是像Optional实例这样的对象,它们通常是具有暂时性.

That sounds like a statement nobody could deny, but let’s look at the actual work of a garbage collector, considering common implementations of modern JVMs and the impact of an allocated object on it, especially objects like Optional instances which are typically of a temporary nature.

垃圾收集器的首要任务是识别仍然存在的对象.名称为垃圾收集器"的重点是识别垃圾,但是垃圾被定义为无法访问的对象,而找出哪些对象无法访问的唯一方法是通过消除过程.因此,第一个任务是通过遍历和标记所有可到达的对象来解决.因此,此过程的成本不取决于分配的对象的总数,而仅取决于仍可以实现的对象.

The first task of the garbage collector is to identify objects which are still alive. The name "garbage collector" puts a focus on identifying garbage, but garbage is defined as unreachable objects and the only way to find out which objects are unreachable, is via the process of elimination. So the first task is solved by traversing and marking all reachable objects. So the costs of this process do not depend on the total amount of allocated objects, but only those, which are still reachable.

第二个任务是使垃圾内存可用于新分配.所有现代垃圾收集器的工作方式是撤离一个完整的区域,将带有该内存的所有活动对象转移到一个新位置,并对其进行修改,而不用迷惑仍可访问的对象之间的内存缺口.在此过程之后,整个块可将内存用于新分配.因此,这又是一个过程,其成本不取决于分配的对象的总数,而仅取决于仍然存在的对象的(一部分).

The second task is to make the memory of the garbage available to new allocations. Instead of puzzling with the memory gaps between still reachable objects, all modern garbage collectors work by evacuating a complete region, transferring all alive objects withing that memory to a new location and adapting the references to them. After the process, the memory is available to new allocations as a whole block. So this is again a process whose costs do not depend on the total amount of allocated objects, but only (a part of) the still alive objects.

因此,如果临时对象Optional在两个垃圾回收周期之间分配和放弃,则可能根本不会对实际垃圾回收过程造成任何费用.

Therefore, an object like a temporary Optional may impose no costs on the actual garbage collection process at all, if it is allocated and abandoned between two garbage collection cycles.

当然有一个收获.每次分配都会减少可用于后续分配的内存,直到没有剩余空间并且必须进行垃圾收集为止.因此,可以说,每次分配都会减少两次垃圾回收运行之间的时间,方法是分配空间的大小除以对象大小.这不仅是很小的一部分,而且还仅适用于单线程方案.

With one catch, of course. Each allocation will reduce the memory available to subsequent allocations until there’s no space left and the garbage collection has to take place. So we could say, each allocation reduces the time between two garbage collection runs by the size of the allocation space divided by the object size. Not only is this a rather tiny fraction, it also only applies to a single threaded scenario.

在像Hotspot JVM这样的实现中,每个线程都将线程本地分配缓冲区(TLAB)用于新对象.一旦TLAB装满,它将从分配空间(又名Eden空间)中获取一个新的.如果没有可用的,将触发垃圾回收.现在,所有线程不可能同时同时达到其TLAB的结尾.因此,对于此时在其TLAB中仍剩余空间的其他线程,如果它们分配了更多仍适合该剩余空间的对象,则不会有任何区别.

In implementations like the Hotspot JVM, each thread uses a thread local allocation buffer (TLAB) for new objects. Once its TLAB is full, it will fetch a new one from the allocation space (aka Eden space). If there is none available, a garbage collection will be triggered. Now it’s rather unlikely that all threads hit the end of their TLAB right at the same time. So for the other threads which still have some space in their TLAB left at this time, it would not make any difference if they had allocated some more objects still fitting in that remaining space.

也许令人惊讶的结论是,不是每个分配的对象都会对垃圾回收产生影响,即由线程分配的不触发下一个gc的纯本地对象可能是完全免费的.

The perhaps surprising conclusion is that not every allocated object has an impact on the garbage collection, i.e. a purely local object allocated by a thread not triggering the next gc, could be entirely free.

当然,这不适用于分配大量对象.大量分配它们会导致线程分配更多的TLAB,并最终比没有的情况更早触发垃圾回收.这就是为什么我们有类似IntStream的类,允许像Stream<Integer>那样处理大量元素而无需分配对象的原因,而将结果作为单个OptionalInt实例提供则没有问题.现在我们知道,单个临时对象对gc的影响很小(如果有的话).

Of course, this does not apply to allocating a large amount of objects. Allocating lots of them causes the thread to allocate more TLABs and eventually trigger the garbage collection earlier than without. That’s why we have classes like IntStream allowing to process a large number of elements without allocating objects, as would happen with a Stream<Integer>, while there is no problem in providing the result as a single OptionalInt instance. As we know now, a single temporary object has only a tiny impact on the gc, if any.

这甚至都没有触及JVM的优化器,如果Escape Analysis已证明该对象纯粹是本地的,则该优化器可以消除热点中的对象分配.

This did not even touch the JVM’s optimizer, which may eliminate object allocations in hot spots, if Escape Analysis has proven that the object is purely local.

这篇关于可选的&lt; T&gt;的GC开销为0.在Java中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆