奇怪的内存使用情况

时间:2015-05-17 18:34:20

标签: java performance memory ram

在创建体素游戏的过程中,我正在为基本的块系统进行一些性能测试。

块在y轴上由16个瓦片组成。 tile是材质ID的Hashmap。 键是一个字节,材质ID是短的。

根据我的计算,一个块应该是12KB +一点点(让我们只说16KB)。 16 * 16 * 16 * 3。 3表示一个字节,一个短(3个字节)。

我基本上不明白的是我的应用程序使用的内存比预期的多得多。实际上每个块大约256KB。它使用大约2GB运行8192个块。请注意,这是块存储性能测试,因此不是整个游戏。

另一个奇怪的事情是每次运行时内存使用量从1.9GB到2.2GB不等。代码中没有随机函数,因此它应该始终是相同数量的变量,数组,元素等。

继承我的代码:

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
        }


    }

}

另一个班级

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

}

我使用Windows任务管理器来监控内存使用情况。 这是一个非常不准确的监控工具,并且可以进行猜测,这可以解释为什么它在不同实例之间的差异。

是什么让每个大块比它应该重20倍?

一个小小的奖励问题,如果你知道:如果我知道我想要找到的索引,那么hashMap或ArrayList会更快吗?

1 个答案:

答案 0 :(得分:3)

  

块在y轴上由16个瓦片组成。 tile是材质ID的Hashmap。键是一个字节,材质ID是短的。

     

根据我的计算,一个块应该是12KB +一点点(让我们只说16KB)。 16 * 16 * 16 * 3。 3表示一个字节,一个短(3个字节)。

那很糟糕。虽然您保持HashMap秘密的大小,但我可以看到您过于乐观。

Map.Entry是一个对象。为其标题添加4或8个字节。

它的关键是一个对象,而不是一个原始对象。计数8个字节。

值相同。

HashMap.Entry存储散列(int,4个字节)和对Entry next的引用(4或8个字节)。 HashMap维护一个对其条目的引用数组(每个元素4或8个字节),默认情况下保持最多75%。

所以我们有更多你期望的东西。确切的值取决于您的JVM,我上面的一些数字可能是错误的。无论如何,你的关系大概是10或更多。

我建议您将代码发布到CR,并提供尺寸估算所需的所有详细信息。考虑使用一些primitive map或者只是一个数组...