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");
}
}