Java 理解参考带宽

Java 理解参考带宽,java,Java,我正在读Richard Warburton写的一本关于java 8的书。在关于原语流的部分中,作者对原语与引用(我的重点)进行了一些解释: 对于执行大量数值运算的算法 装箱与使用的额外内存带宽相结合的拆箱 通过分配装箱对象可以显著降低代码速度 带宽是多少?对于原语,我们在内存中有它们的实际值,可以直接使用它们 反过来,对于引用,我们使用指向堆的指针,并在某个对象上调用方法,我们必须通过给定的指针执行间接寻址,然后才能调用该方法。这算是带宽吗 实际上,我们真的需要担心带宽吗?现实中的计算机在从内存

我正在读Richard Warburton写的一本关于java 8的书。在关于原语流的部分中,作者对原语与引用(我的重点)进行了一些解释:

对于执行大量数值运算的算法 装箱与使用的额外内存带宽相结合的拆箱 通过分配装箱对象可以显著降低代码速度

带宽是多少?对于原语,我们在内存中有它们的实际值,可以直接使用它们

反过来,对于引用,我们使用指向堆的指针,并在某个对象上调用方法,我们必须通过给定的指针执行间接寻址,然后才能调用该方法。这算是带宽吗


实际上,我们真的需要担心带宽吗?

现实中的计算机在从内存中检索字节/字的速度上有限制,从CPU缓存中读取的速度更快,从L1/L2/L3/之外的内存中读取的速度更慢。。。缓存

当我们处理一个大型的原语/盒装流时,我们可以假设CPU缓存中没有集合元素,它们需要从主存中获取

在适用于OpenJDK的过于简化的情况下,内存中的对象将包含对其
java.lang.Class
及其所有超类(用于检查强制转换和相关)的引用,然后是其字段。这可能相当大,例如,对于装箱的
java.lang.Integer
,它可能需要维护对
Class
Class
的引用。不用说,这比原语所需的32位要大得多


当迭代/流式处理
Integer
s的集合时,有必要将这些对象加载到内存中,对于元素上的简单数字操作,内存成为瓶颈

现实的计算机在从内存中检索字节/字的速度上有一个限制,从CPU缓存读取的速度更快,从L1/L2/L3/…之外的内存读取的速度较慢。。。缓存

当我们处理一个大型的原语/盒装流时,我们可以假设CPU缓存中没有集合元素,它们需要从主存中获取

在适用于OpenJDK的过于简化的情况下,内存中的对象将包含对其
java.lang.Class
及其所有超类(用于检查强制转换和相关)的引用,然后是其字段。这可能相当大,例如,对于装箱的
java.lang.Integer
,它可能需要维护对
Class
Class
的引用。不用说,这比原语所需的32位要大得多


当迭代/流式处理
Integer
s的集合时,有必要将这些对象加载到内存中,对于元素上的简单数字操作,内存成为瓶颈

基本上是的。当处理装箱对象而不是基本体时,您会有引用开销和对象开销。然而,这不是你应该经常思考的事情


当然,如果您不需要对象数组,您需要小心使用例如
int[]
而不是
Integer[]
,但是在您需要担心基元与装箱之前,通常有更好的优化位置。在DB或网络绑定系统中,CPU缓存通常对应用程序的最终吞吐量几乎没有影响。在CPU受限的系统中,正如hexafraction的回答所解释的,这自然更为相关。

基本上是的。当处理装箱对象而不是基本体时,您会有引用开销和对象开销。然而,这不是你应该经常思考的事情


当然,如果您不需要对象数组,您需要小心使用例如
int[]
而不是
Integer[]
,但是在您需要担心基元与装箱之前,通常有更好的优化位置。在DB或网络绑定系统中,CPU缓存通常对应用程序的最终吞吐量几乎没有影响。在CPU受限的系统中,正如Hexafrance的回答中所解释的,这自然更为相关。

IMHO,这意味着装箱对象需要比基本类型多得多的内存。而且,在java中没有指针。基本类型总是存储在堆栈上,对象总是存储在堆上。在应用程序中工作的已装箱对象的实例始终引用堆上的原始对象。因此,我认为,对于带宽,作者只是意味着应用程序必须处理的内存会变得更大,因为它使用了许多包含原语的盒装对象,而不是直接使用原语。IMHO,这意味着盒装对象需要比原语类型多得多的内存。而且,在java中没有指针。基本类型总是存储在堆栈上,对象总是存储在堆上。在应用程序中工作的已装箱对象的实例始终引用堆上的原始对象。因此,我认为,对于带宽,作者只是意味着应用程序必须处理的内存会变得更大,方法是使用许多包含原语的装箱对象,而不是直接使用原语。