分析内存使用情况:Java与C ++可以忽略不计?


9

用Java编写的整数对象的内存使用情况与用C ++编写的整数对象的内存使用情况如何比较\对比?差异可忽略不计吗?没有不同?有很大的不同吗?我猜是一样的,因为int是int而不管语言(?)

我之所以这样问,是因为我正在阅读了解何时知道程序的内存需求将阻止程序员解决给定问题的重要性。

让我着迷的是创建单个Java对象所需的内存量。以一个整数对象为例。如果我错了,请纠正我,但是Java整数对象需要24个字节的内存:

  • 4个字节的int实例变量
  • 16字节的开销(引用对象的类,垃圾收集信息和同步信息)
  • 4字节的填充

再举一个例子,Java数组(作为对象实现)需要48个字节以上:

  • 标头信息的24个字节
  • 16个字节的对象开销
  • 4个字节的长度
  • 4个字节用于填充
  • 加上存储值所需的内存

与使用C ++编写的相同代码相比,这些内存使用情况如何?

我过去对编写的C ++和Java程序的内存使用情况一无所知,但是现在,我开始学习算法,对计算机的资源有了更大的了解。


6
什么是C ++中的“整数对象”?int?如果是这样,您应该将其与intJava中的进行比较,Integer只要C ++ int是32位,就不应该进行比较。
2012年

+1如果我创建了一个只有一个int变量的c ++类,则将其实例化
Anthony

3
一个int不是一个

1
只有一个int成员的C ++通常不会有任何开销。它将使用与平台用于存储int的空间一样多的空间(在当前PC平台上通常为4个字节)。
德克·霍尔索普

对于Java程序员对内存感到好奇的+1。最重要的是,内存意识是决定现代体系结构性能的最重要因素。
imallett 2014年

Answers:


15

这取决于平台和实现。

C ++保证的大小char恰好是一个字节,至少8位宽。然后,a的大小short int至少为16位且不小于char。的大小int至少等于的大小short int。的大小long int至少为32位,并且不小于int。

sizeof(char) == 1; sizeof(long int) >= sizeof(int) >= sizeof(short int) >= sizeof(bool) >= sizeof(char).

C ++的实际内存模型非常紧凑且可预测。例如,对象,数组或指针中没有元数据。结构和类就像数组一样是连续的,但是可以在必要和需要的地方放置填充。

坦白地说,这种比较充其量是愚蠢的,因为Java内存的使用更多地取决于Java实现而不是其运行的代码。


1
是的,但是为了比较起见,我想我们应该假设大小相等的整数类型(即使它们只能以不同的名称使用)。毕竟,不同的大小意味着不同的语义,并且在许多(并非全部)通用平台上,大小是相同的,或者以不同的名称提供了相同大小的整数。

OP的注意事项:您最好自己选择整数的大小-如果要在C ++中使用32位int,可以使用int32_t
K.Steff

9

大多数答案似乎都忽略了几个相当重要的观点。

首先,在一个可怕的很多的Java,你几乎再也看不到原料int-几乎所有的使用是的Integer,这样的事实,即int可能是(约)相同的尺寸为intC或C ++是几乎不相干,除了那(根据我的经验,仅使用int而不是的代码比例很小Integer

其次,单个对象的大小几乎与整个程序的内存占用无关。在Java中,程序的内存占用量主要与垃圾回收器的调整方式有关。在大多数情况下,已将GC调整为最大速度,这在很大程度上意味着尽可能不频繁地运行GC。

我目前没有可用的链接,但是有一些测试表明Java可以以与C相同的速度运行,但是为此,您必须运行GC的次数很少,其使用量大约是C的7倍记忆。那不是因为单个对象的大小是原来的7倍,而是因为如果您经常这样做,GC可能会变得非常昂贵。更糟糕的是,GC仅在可以“证明”不再有访问对象的方式时才释放内存,而不仅仅是在您知道使用完该对象时才释放内存。这意味着,即使您更频繁地运行GC以最大程度地减少内存使用量,您也可能仍可以计划在典型程序中拥有更大的内存占用量。在这种情况下,您可以将系数减小为2或3而不是7。但是,即使您过分沉迷,也不要1

根据情况,还有另一个因素可能会或可能不会很重要:JVM本身占用的内存。这或多或少是固定的,因此,如果该应用程序不需要自己的大量存储,则百分比可能很大,或者如果该应用程序需要存储很多,则百分比可能很小。至少在我的机器上,即使是最琐碎的Java应用程序似乎也占据了20-25兆字节的容量(对于琐碎的程序可能超过1000倍,对于大型程序可能几乎很小)。


1这并不是说,没有人可能会设法以接近C ++的足迹来编写Java。这只是说,只是有对象的相同数量/大小,并运行GC真的经常不会让你有一个规则。


7
关于您的第一点:我不是Java专家,但是我见过的Java API从未使用过Integer(为什么会使用它们?)intInteger由于类型擦除,只有通用集合别无选择,只能使用,但是如果您愿意,可以使用专用于特定int类型的实现或所需的任何原始类型替换它们。然后有一个临时框,用于传递通用包装代码(例如,需要使用的所有内容Object[])。除此之外,您还有GC空间开销的来源吗?我真的不怀疑,我只是好奇。


9

我希望您认识到所有这些都是针对Java和C ++的深层实现定义的。话虽如此,Java的对象模型需要大量空间。

C ++对象通常不需要成员所需要的任何存储。请注意(与Java不同,在Java中,用户定义的所有内容都是引用类型),客户端代码可以将对象用作值类型或引用类型,即,一个对象可以存储指向另一个对象的指针/引用,或者直接存储该对象没有间接。如果有任何virtual方法,则每个对象都需要一个额外的指针,但是很多有用的类被设计为无需多态性就可以相处并且不需要这样做。没有GC元数据,也没有每个对象的锁定。因此,class IntWrapper { int x; public: IntWrapper(int); ... };对象不需要的空间比plain所需的空间更多int,并且可以直接(即无间接)放置在集合和其他对象中。

数组之所以棘手,仅仅是因为没有与C ++中的Java Array通用的预制组件。您可以简单地分配一堆对象new[](绝对没有开销/元数据),但是没有长度字段-实现可能存储了一个对象,但您无法访问它。std::vector是一个动态数组,因此具有额外的开销和更大的接口。std::array和C样式的数组(int arr[N];),需要一个编译时常量。从理论上讲,它应该只是对象的存储空间,再加上一个长度的整数-但是由于可以动态调整大小和功能齐全的接口而几乎没有多余的空间,因此在实践中就可以做到这一点。请注意,所有这些集合以及所有其他集合,默认情况下都是按值存储对象,从而节省了间接寻址和引用空间,并改善了缓存行为。您必须显式存储指针(请使用智能指针)以进行间接访问。

上面的比较并不完全公平,因为其中一些节省是由于不包括Java包含的功能而获得的,并且它们的C ++等效项通常没有Java等效项(*)更好。virtual用C ++ 实现的通用方法所产生的开销与virtual用Java 实现的通用方法一样多。要获得锁,您需要一个功能齐全的互斥对象,该对象很可能大于几位。获取参考计数(不是等效于GC,因此不应使用,但有时很有用),您需要一个智能指针,该指针会添加一个引用计数字段。除非精心构造对象,否则引用计数,智能指针对象和引用对象位于完全独立的位置,即使正确构造它,共享指针也可能(必须?)仍然是两个指针而不是一个。再说一次,良好的C ++样式使用这些功能不足以解决问题-实际上,编写良好的C ++库的对象使用较少。这不一定意味着总体上减少了内存使用量,但确实意味着C ++在这方面具有良好的领先优势。

(*)例如,通过将类型信息与各种标志合并,并删除对象的锁定位,可以获得虚拟调用,身份哈希码和某些对象仅使用一个单词(许多其他对象使用两个单词)锁定不太可能需要锁。有关此优化和其他优化的详细说明,请参见David F. Bacon,Stephen J. Fink和David Grove 的Java对象模型的节省空间和时间的实现(PDF)。


3

如果两个实现使用相同的整数大小和内存对齐方式int,则java中的plain 占用的空间与intC ++中的完全一样。

int'对象'(装箱的整数,即class的实例Integer)承担Java中类实例的所有开销,因此它比intC ++中的int 大得多。但是,如果要在C ++中为对象配备与Java对象即用的相同功能(多态性,装箱,垃圾回收,RTTI),那么最终可能会得到一个相等的对象尺寸。

还有一些优化方面的考虑;由于执行模型和编程范例不同,因此两种语言都不可能以相同的方式解决任何非平凡的问题,因此,在此级别上比较存储大小没有任何不可思议的意义。

是的,默认情况下,Java对象比C ++类具有更多的开销,但是它们具有更多的功能,这导致了不同的编程风格-好的程序员可以利用这两种语言的优缺点。


+1,我现在了解了Java中更多的开销,但更多了Java功能,谢谢
Anthony
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.