散列映射内存开销 [英] Hash Map Memory Overhead

查看:129
本文介绍了散列映射内存开销的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述




  • 实现是一个HashMap数组$ Entry对象:

  • 每个HashMap $ Entry包含:
    - int KeyHash
    - Object next
    - Object key
    - 对象值


  • 默认容量为16个条目

  • 128字节
    HashMap的开销为48字节,
    数组加上(16 +(entries * 4bytes)) - HashMap $ Entry的额外开销对象
  • 每个键的额外32字节值value条目HashMap的开销是
    ,因此: - 48字节,每个条目加36个字节


    任何人都可以给我解释HashMap的开销是48字节,加上(16 +(entries * 4bytes) )为
    数组
    每个键的额外32字节↔值条目HashMap的开销为

    因此: - 48字节,p lus每个条目36个字节
    ???

    我无法理解这些结论是如何得出的,即我们如何看到这个最终存储器哈希映射的详细信息。 Java中的对象消耗>您可能想要阅读这个SO问题。对象开销会因不同的CPU架构,VM实现和不同的Java版本(例如OOPS,还有 fixnums 等建议。)



    但让我们 自己查看 OpenJDK 7, HashMap 类:







    HashMap


    家政信息。 大概8个字节。



    实现中有三个字段保存由 keySet() code>, values() entrySet()方法。在32位机器上有三个指针,即 12个字节

      //来自AbstractMap 
    瞬态易失性Set< K> keySet = null;
    临时变量集合< V> values = null;

    //从HashMap
    私有瞬态Set< Map.Entry< K,V>> entrySet = null

    有三个 int 字段: size 阈值 modCount float 字段: 4个字节。



    表指针本身( Entry []表))。 4个字节。



    static final 编译时常量)

    给我们的所有内容 40字节的平面成本 HashMap 实例。这不是48个字节,我不知道为什么。也许我错过了一些东西,也许你的文字提到了其他版本。这些东西有时候会有所改变。过去可能有一个额外的领域。也许它是从40到48字节(但它不应该)填充。





    < array strong> 16 +(entries * 4 bytes)for array

    当构造 HashMap 时,我们需要对它进行计数。



    一个实例化的数组需要<8>字节的管家数据, 4字节用于长度属性。这是 12个字节,而不是16.再次,不知道从哪里来。



    每个条目都是指向 Entry 对象,因此每个条目的 4个字节。这很简单。





    每个键另有32个字节↔值条目

    同样, 8个字节管家。



    现在,这些字段:

      final K key; //引用,4字节
    V值; //一个引用,4个字节
    条目< K,V>下一个; //引用,4个字节
    final int hash; //整数原语,4字节

    16个字节。



    这是每个条目最终计数为<24>字节。再次,这不是36。






    我不知道你从那里得到的数字来自哪里。那可能是IBM vm吗?这可能是一个64位的操作系统?也许现在的内务处理信息是16字节(Java 8会改变什么?)。

    无论如何,我试图根据自己的最佳知识来计算内存消耗。

    >

    I was studying about internal structure of Hash Map where i came across following details:

    • Implementation is an array of HashMap$Entry objects:

    • Each HashMap$Entry contains: – int KeyHash – Object next – Object key – Object Value

    • Default capacity is 16 entries

    • Empty size is 128 bytes

    • Overhead is 48 bytes for HashMap, plus (16 + (entries * 4bytes)) for array – Plus overhead of HashMap$Entry objects

    • Additional 32bytes per key ↔ value entry Overhead of HashMap is
      therefore: – 48 bytes, plus 36 bytes per entry

    Can anyone please explain me "Overhead is 48 bytes for HashMap, plus (16 + (entries * 4bytes)) for array" and "Additional 32bytes per key ↔ value entry Overhead of HashMap is
    therefore: – 48 bytes, plus 36 bytes per entry"
    ???

    I can't understand how these conclusions came i.e. how we came across this final memory details about hash map.

    解决方案

    You might want to read this SO question. The object overhead will vary between different CPU architectures, VM implementations and between different Java versions (e.g. OOPS, there are also suggestions of fixnums etc.).

    But let's see for ourselves for OpenJDK 7, the HashMap class:


    Overhead is 48 bytes for HashMap

    Housekeeping info. Presumably 8 bytes.

    There are three fields in the implementation that hold the views made by keySet(), values() and entrySet() methods. Three pointers, that's 12 bytes on a 32-bit machine.

    // from AbstractMap
    transient volatile Set<K>        keySet = null;
    transient volatile Collection<V> values = null;
    
    // from HashMap
    private transient Set<Map.Entry<K,V>> entrySet = null
    

    There are three int fields: size, threshold and modCount. 12 bytes.

    There is one float field: loadFactor. 4 bytes.

    The table pointer itself (Entry[] table). 4 bytes.

    (the static final fields don't count, they are compile-time constants)

    All that gives us 40 bytes flat cost of a HashMap instance. It's not 48 bytes and I don't know why. Maybe I missed something, maybe your text referred to other version. These things sometimes change a little. There may have been an extra field in the past. Maybe it's padded from 40 to 48 bytes (but it shouldn't).


    16 + (entries * 4 bytes) for array

    The Entry[] table table is instantiated when the HashMap is constructed, we need to count it, too.

    An instantiated array takes 8 bytes of housekeeping data, 4 bytes for the length property. That's 12 bytes, not 16. Again, no idea where that comes from.

    Every entry is a pointer to an Entry object, so that's 4 bytes per entry. That was easy.


    Additional 32 bytes per key ↔ value entry

    Again, 8 bytes of housekeeping.

    Now, the fields:

    final K key;    // a reference, 4 bytes
    V value;        // a reference, 4 bytes
    Entry<K,V> next;  // a reference, 4 bytes
    final int hash; // an integer primitive, 4 bytes
    

    16 bytes.

    That's a final count of 24 bytes per entry. Again, that's not 36.


    I have no idea where the numbers you got there come from. Could that be an IBM vm? Could that be a 64-bit OS? Maybe the the housekeeping info is 16 bytes nowadays (will Java 8 change anything?).

    Anyway, I tried to compute the memory consumption to my best knowledge.

    这篇关于散列映射内存开销的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆