使用字符串vs byte []作为值,地图中的内存使用情况

问题描述:

我在多个使用byte []而不是string的地方读取它会节省您的内存。我想用jol进行测试。使用字符串vs byte []作为值,地图中的内存使用情况

这里我的测试:

public static void main (String[] args) throws java.lang.Exception{ 
    System.out.println(VMSupport.vmDetails()); 
    String StrByte = GraphLayout.parseInstance(sizeOfStrByteMap(100000)).toFootprint(); 
    String ByteByte = GraphLayout.parseInstance(sizeOfByteByteMap(100000)).toFootprint(); 
    String StrStr  = GraphLayout.parseInstance(sizeOfStrStrMap(100000)).toFootprint(); 
    System.out.println(StrByte); 
    System.out.println(ByteByte); 
    System.out.println(StrStr); 
} 

public static HashMap<String, String> sizeOfStrStrMap(int size) { 
    String value = "this is the sample value"; 

    HashMap<String, String> map = new HashMap<>(); 
    for (int i = 0; i < size; i++) { 
     map.putIfAbsent(Integer.toString(i), value); 
    } 
    return map; 
} 

public static HashMap<String, byte[]> sizeOfStrByteMap(int size) { 
    byte[] value = "this is the sample value".getBytes(); 

    HashMap<String, byte[]> map = new HashMap<>(); 
    for (int i = 0; i < size; i++) { 
     map.putIfAbsent(Integer.toString(i), value); 
    } 
    return map; 
} 

public static HashMap<byte[], byte[]> sizeOfByteByteMap(int size) { 
    byte[] value = "this is the sample value".getBytes(); 

    HashMap<byte[], byte[]> map = new HashMap<>(); 
    for (int i = 0; i < size; i++) { 
     map.putIfAbsent(Integer.toString(i).getBytes(), value); 
    } 
    return map; 
} 

这里是我的结果:

Running 64-bit HotSpot VM. 
Using compressed oop with 3-bit shift. 
Using compressed klass with 3-bit shift. 
Objects are 8 bytes aligned. 
Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes] 
Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes] 

// StrByteMap 
[email protected] footprint: 
    COUNT  AVG  SUM DESCRIPTION 
     1  184  184 [B 
    100000  31 3120000 [C 
     1 1048592 1048592 [Ljava.util.HashMap$Node; 
    100000  24 2400000 java.lang.String 
     1  48  48 java.util.HashMap 
    100000  32 3200000 java.util.HashMap$Node 
    300003    9768824 (total) 

// ByteByteMap 
[email protected] footprint: 
    COUNT  AVG  SUM DESCRIPTION 
    100001  24 2400184 [B 
     1 1048592 1048592 [Ljava.util.HashMap$Node; 
     1  48  48 java.util.HashMap 
    100000  32 3200000 java.util.HashMap$Node 
    200003    6648824 (total) 


// StrStrMap 
[email protected] footprint: 
    COUNT  AVG  SUM DESCRIPTION 
    100001  31 3120344 [C 
     1 1048592 1048592 [Ljava.util.HashMap$Node; 
    100001  24 2400024 java.lang.String 
     1  48  48 java.util.HashMap 
    100000  32 3200000 java.util.HashMap$Node 
    300004    9769008 (total) 

正如你所看到的,StrByteMap和StrStrMap之间的内存使用率几乎是相同的。我在这里测试错了吗?

UPDATE: 请参考下面@Amod潘迪的question,我也想知道为什么。

+0

鉴于数组字节和字符串是不可互换的东西,这个问题是没有意义的。 – Raedwald

对于Map测试,您将放入相同的值引用,因此它不会占用太多空间。以同样的方式,你有不同的关键你需要使价值不同或如你所见,值类型的选择没有太大的区别。

+1

另外应该注意的是'getBytes()'取决于系统默认的语言环境。如果它是UTF-16,结果会有所不同。 –

+0

@TagirValeev OP似乎使用ASCII,但对于某些字符,不同的编码也会有不同的长度,给出不同的大小+1 –

我觉得很奇怪。

// StrByteMap 
[email protected] footprint: 
    COUNT  AVG  SUM DESCRIPTION 
     1  184  184 [B 
    100000  31 3120000 [C 

有一个byte arrary实例和100000个char数组实例。这是100001的情况下的strstr

// StrStrMap 
[email protected] footprint: 
    COUNT  AVG  SUM DESCRIPTION 
    100001  31 3120344 [C 

所以,即使你已经存储字节数组的内存占用字符数组的字符数组!

另一点是ByteByte字节数组对象的平均大小是24,它小于184(StrByteMap)的字节数组大小,并且在所有三种情况下不应该总计数相同。

+0

我不知道。我也有兴趣知道为什么。也许有人可以解释? – LuckyGuess