在64位Java中,每个对象实例都倾向于包含一个192-bit header,其中包含
这可能导致小对象占用大量内存。
尼姆的情况是否类似?用两种语言类似编写的大型应用程序(运行时大小可忽略不计)会使用大约相同的内存量吗?
更新 :
我进行了一些实验,其中我使用100M float64
个元素构建了一个幼稚的单链接列表,并对其进行了多次迭代。
Java实际使用的内存比Nim低25%。
完整的Nim代码:
htop
这使用3.1GB,每个type Node = ref object
data : float64
next : Node
echo "Running"
proc create(n : int): Node =
var
tmp = Node(data: 0, next: nil)
for i in 1..<n:
tmp = Node(data: i.float64, next: tmp)
return tmp
proc sum(x: Node): float64 =
var
tmp: float64 = 0
y = x
while true:
tmp += y.data
y = y.next
if y.isNil:
return tmp
proc sums(x: Node, n: int): float64 =
var tmp: float64 = 0
for i in 0..<n:
tmp += sum(x) / n.float64
return tmp
let x = create(1000 * 1000 * 100)
echo "Created"
echo sums(x, 100)
echo "Finished"
的输出为269位,而Java使用Node
的非常相似的代码使用203位。这少于192位标头+ 128位结构。我猜想某种JIT优化可以使Java使用更少的内存来运行。
完整的Java代码:
Node
Node.java
public class Node {
double data = 0;
Node next = null;
}
SListTest.java
答案 0 :(得分:2)
在Nim中,您还可以将对象放入堆栈中,因此不需要垃圾回收,仅占用与对象中的成员一样多的空间。将自动分配的对象放在堆上时,存在一些垃圾回收内存开销,但对象本身仍保持其成员大小(当然还要加上填充)。
答案 1 :(得分:2)
对于Nim和HotSpot(请注意,并非所有Java实现都需要使用相同的方法),基本分配需要一个字表示GC信息,一个字表示类型信息(Nim,HotSpot) 。在HotSpot中,如果使用-XX:+UseCompressedOops
不需要超过32GB的堆空间,则可以在64位计算机上将类型信息减少到半个字。
Java中的现代锁定实现不会产生额外的开销; GC字is also used for a thin locking scheme,并在需要时扩展为指向完整监视器的指针。因此,默认情况下,每个对象有两个开销字。
在您的示例中,在64位计算机上,Nim中每个对象的内存消耗为四个字:
这种大小的1e8分配需要原始量32 * 1e8 = 3.2e9字节,即约3 GB。
我要补充一点,拥有很多小的分配往往bad for memory locality甚至不算那么多分配的成本,因此通常应尽可能避免。 (动态)数组几乎总是比链表更可取。