Reputation: 645
In the process of creating a voxel game, I'm doing some performance tests, for the basic chunk system.
A chunk is made of 16 tiles on the y axis. A tile is a Hashmap of material ids. The key is a byte, and the material id is a short.
According to my calculations a chunk should be 12KB + a little bit (Let's just say 16KB). 16*16*16*3. 3 is for a byte and a short(3 bytes).
What I basically don't understand is that my application uses much more memory than expected. Actually around 256KB for each chunk. It uses around 2GB running 8192 chunks. Notice that this is chunk storage performance test, and therefore not a whole game.
Another strange thing is that the memory usage varies from 1.9GB to 2.2GB each time I run it. Theres no randomizer in the code, so it should always be the same amount of variables, arrays, elements etc.
Heres my code:
public class ChunkTest {
public static void main(String[] args) {
List <Chunk> chunks = new ArrayList <Chunk>();
long time = System.currentTimeMillis();
for(int i = 0; i<8192; i++) {
chunks.add(new Chunk());
}
long time2 = System.currentTimeMillis();
System.out.println(time2-time);
System.out.println("Done");
//System.out.println(chunk.getBlock((byte)0, (byte)0, (byte)0));
while(1==1) {
//Just to keep it running to view memory usage
}
}
}
And the other class
public class Chunk {
int x;
int y;
int z;
boolean solidUp;
boolean solidDown;
boolean solidNorth;
boolean solidSouth;
boolean solidWest;
boolean solidEast;
private HashMap<Byte, HashMap<Byte, Short>> tiles = new HashMap<Byte, HashMap<Byte, Short>>();
public Chunk() {
HashMap<Byte, Short> tile;
//Create 16 tiles
for(byte i = 0; i<16;i++) {
//System.out.println(i);
tile = new HashMap<Byte, Short>();
//Create 16 by 16 blocks (1 is the default id)
for(short e = 0; e<256;e++) {
//System.out.println(e);
tile.put((byte) e, (short) 1);
}
tiles.put(i, tile);
}
}
public short getBlock(byte x, byte y, byte z) {
HashMap<Byte, Short> tile = tiles.get(y);
short block = tile.get((byte)(x+(z*16)));
return block;
}
}
I'm using windows task manager to monitor the memory usage. Is that a very inaccurate tool to monitor, and does it kind of guess, which would explain why it varies from instance to instance.
And what is making each chunk 20 times heavier than it should?
A little bonus question, if you know: If I know the index of what I'm trying to find, is hashMap or ArrayList faster?
Upvotes: 2
Views: 113
Reputation: 46492
A chunk is made of 16 tiles on the y axis. A tile is a Hashmap of material ids. The key is a byte, and the material id is a short.
According to my calculations a chunk should be 12KB + a little bit (Let's just say 16KB). 16*16*16*3. 3 is for a byte and a short(3 bytes).
That's bad. Though you're keeping the size of the HashMap
secret, I can see you're too optimistic.
A Map.Entry
is an object. Add 4 or 8 bytes for its header.
Its key is an object, never a primitive. Count 8 bytes.
The same for the value.
A HashMap.Entry
stores the hash (int
, 4 bytes) and a reference to Entry next
(4 or 8 bytes). The HashMap
maintains an array of references to its entries (4 or 8 bytes per element), which by default kept at most 75% full.
So we have much more that what you expected. The exact values depends on your JVM and some of my above figures may be wrong. Anyway, you're off by a factor of at maybe 10 or more.
I'd suggest you to post you code to CR with all the details needed for the size estimation. Consider using some primitive map or maybe just an array...
Upvotes: 3