【问题标题】:Using string vs byte[] as value, Memory usage in map使用字符串与字节 [] 作为值,映射中的内存使用情况
【发布时间】:2016-02-27 20:41:22
【问题描述】:

我在多个地方读到它,使用 byte[] 而不是 string 可以节省内存。我想使用jol 对其进行测试。

这是我的测试:

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
java.util.HashMap@15327b79d 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
java.util.HashMap@a9d12ad 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
java.util.HashMap@716d90fad 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 之间的内存使用几乎相同。我在这里测试错了吗?

更新: 请看下面@Amod Pandey 的question,我也想知道为什么。

【问题讨论】:

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

标签: java memory jol


【解决方案1】:

对于 Map 测试,您将放入相同的值引用,因此它不会占用太多空间。就像您拥有不同的键一样,您需要使值不同,或者如您所见,值类型的选择并没有太大区别。

【讨论】:

  • 还应该注意getBytes() 取决于系统默认语言环境。如果是 UTF-16,结果会有所不同。
  • @TagirValeev OP 似乎正在使用 ASCII,但对于某些字符,不同的编码也会有不同的长度,给出不同的大小 +1
【解决方案2】:

我觉得很奇怪。

// StrByteMap
java.util.HashMap@15327b79d footprint:
     COUNT       AVG       SUM   DESCRIPTION
         1       184       184   [B
    100000        31   3120000   [C

有 1 个字节数组实例和 100000 个 char 数组实例。在 StrStr 案例中是 100001 字符数组

// StrStrMap
java.util.HashMap@716d90fad footprint:
     COUNT       AVG       SUM   DESCRIPTION
    100001        31   3120344   [C

所以即使你存储了字节数组,内存占用也是字符数组!!

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

【讨论】:

  • 我不知道。我也有兴趣知道为什么。也许有人可以解释一下?
猜你喜欢
  • 1970-01-01
  • 2017-07-11
  • 2019-03-21
  • 1970-01-01
  • 2020-09-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多