In 64-bit Java, each object instance tends to include a 192-bit header, containing
- the class pointer,
- flags and
- locks (64 bits each).
This can cause a large memory overhead for small objects.
Is the situation similar for Nim? Would a large application (where the size of the runtime is negligible), written similarly in the two languages, use about the same amount of memory?
Update:
I ran some experiments in which I build a naive singly-linked list with 100M float64
elements and iterate through it many times.
Java is actually using 25% less memory than Nim, according to htop
.
Complete Nim code:
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"
This uses 3.1GB, which comes out to 269 bits per Node
, whereas Java uses 203 bits per Node
in very similar code. This is less than 192bit header + 128bit structure. I'm guessing that some kind of JIT optimization makes Java run using less memory.
Complete Java code:
Node.java
public class Node {
double data = 0;
Node next = null;
}
SListTest.java
public class SListTest {
static Node create(int n) {
Node tmp = new Node();
for(int i = 1; i < n; ++i) {
Node p = new Node();
p.data = i;
p.next = tmp;
tmp = p;
}
return tmp;
}
static double sum(Node x) {
double tmp = 0;
while(x != null) {
tmp += x.data;
x = x.next;
}
return tmp;
}
static double sums(Node x, int n) {
double tmp = 0;
for(int i = 0; i < n; ++i)
tmp += sum(x);
return tmp / n;
}
public static void echo(String s) {
System.out.println(s);
System.out.flush();
}
public static void main(String[] args) {
echo("Started");
Node p = create(1000 * 1000 * 100);
echo("Created");
double tmp = sums(p, 100);
System.out.printf("%f\n", tmp);
echo("Finished");
}
}