假设我在一个哈希图中存储了1000个对象。扩展了此哈希图,使我可以将三维坐标映射到其中存储的对象。内部的对象具有固定的大小。哈希键是一个长整数。

我将如何计算(数学上)此结构的可能开销?

  • 是否足够重要,例如,如果内部数据在256mb左右,那么开销会很重要吗?
  • 是否有可靠的方法(除探查器外,在某些情况下我发现它不可靠)以数学方式计算其开销应为多少?

  • 我对哈希表的总大小不感兴趣-仅会产生使用哈希表的开销。例如,如果我有10个整数,则它们是4个字节,所以是40个字节。如果将它们粘贴在数组中,则会得到12字节的恒定开销-对象头为8,长度为4。如果将它们放在另一个结构(例如TreeSet)中,由于树需要节点,我的开销将不是恒定的-因此我可能会得到以n表示的开销,其中n是集合中的项目数。

    对我来说,有些事情是显而易见的,这里我将作为起点。
  • 我将需要存储至少1000个long。这些是可为空的类型,因此它们实际上是对象。因此,我将假定所使用的8字节长的整数的对象标头也为8字节。我将添加16n倍。
  • 我还将需要引用每个对象,无论对象是否已从地图中调出并正在使用中,该引用都必须存在。因此每个对象额外需要8个字节。我们可以将其计入数据大小,但由于引用位于哈希图中,因此我认为最好将它们作为开销的一部分。我的逻辑如下:如果我从哈希图中取出所有数据并将其存储在变量中,则只要不删除这些数据对象,那n个引用仍将存在于哈希图中,如果不这样做的话。对象集是恒定的,尽管可以使用其他密钥来回收它们。
  • 哈希图本身的开销为8个字节。
  • 哈希图必须存储内部的项目数(或者,我认为!),即4个字节。
  • 我将无知地假设哈希键在数组中,并按哈希键顺序排序。这是数组的12个字节。
  • 我也将无知地假设对象位于匹配的数组中,当找到键时它将取消引用。我会猜另外12个字节。

  • 这给了我一个多项式方程:36 + 24n

    因此,我猜测使用长键的1000个数据对象的开销为24036字节。这有点微不足道的开销,但我的问题是,坐在那里的实际开销是多少?

    第二个有效的问题是,不同的JVM有多少不同?有没有JVM独立的方法来解决?为了说明我的意思,请考虑仅具有32位对象标头的JVM-在查看数组时,您可能会说,即使大小因JVM而异,但可以合理估计数组的开销将变为8字节而不是在这种情况下为12。

    我假设在相同版本的Java中实现了HashMap的固定实现。

    我可以尝试阅读源代码或运行概要分析,但是这可能会基于我的JVM产生误导性的结果。我正在寻求您的帮助-也许是一个知道的人-获取一些我们俩都不了解情况的信息。谢谢!

    参见下面的答案,实际估算可以表示为:

    每个条目8个字,每个长8个字节,再加上8个字节的hashmap对象标头。

    在我目前的环境(32位操作系统)中,使1个字= 4个字节。
  • 在32位环境中为40n + 8:对于1000个条目为〜40k
  • 在64位环境中
  • 72n + 8:每1000个条目〜72k。

  • 因此,似乎不足100 KB。

    最佳答案

    以下blog post提供了有关该主题的一些松散数学。
    google code site提供了如何完成这些操作的说明。

    在链接腐烂的情况下引用链接:

    This is the cheat-sheet I compiled.
    
    To compute the cost of a single (key, value) entry:
    
        If you use HashMap or ConcurrentHashMap, the cost is 8 words (32 bytes)
    
    
     So, consider this example from the javadoc:
    
       LoadingCache graphs = CacheBuilder.newBuilder()
           .maximumSize(10000)
           .expireAfterWrite(10, TimeUnit.MINUTES)
           .removalListener(MY_LISTENER)
           .build(
               new CacheLoader() {
                 public Graph load(Key key) throws AnyException {
                   return createExpensiveGraph(key);
                 }
               });
    
    
    The cost of an Entry in this structure this is computed as follows:
    
        It's a Cache: +12 words
        It uses maximumSize(): +4 words
        It uses expiration: +4 words
    
    Thus, each (key, value) entry would have a footprint of 20 words (thus 80 bytes in a 32bit VM, or 160 in a 64bit one).
    
    To estimate the overhead imposed in the garbage collector, one could count how many references (pointers) each entry introduces, which the garbage collector would have to traverse to compute object reachability. The same list again, this time only counting references:
    
        If you use HashMap or ConcurrentHashMap, the cost is 5 references
    

    关于java - 用Java计算HashMap开销,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11565554/

    10-11 10:52