所以我正在阅读Peter Norvig的IAQ(不常见的问题 - 链接)并偶然发现:
您可能会惊讶地发现,在Sun JDK VM中,Object需要16个字节或4个字.这分解如下:有一个双字标题,其中一个字是指向对象类的指针,另一个字指向实例变量.即使Object没有实例变量,Java仍然为变量分配一个单词.最后,有一个"句柄",它是另一个指向双字头的指针.Sun表示,这种额外的间接性使垃圾收集变得更加简单.(已经有高性能的Lisp和Smalltalk垃圾收集器在至少15年内没有使用额外级别.我听说但尚未确认Microsoft JVM没有额外的间接级别.)
一个空的新的字符串()需要40个字节,或10个字:指针开销3个字,3个字的实例变量(开始索引,结束索引,和字符数组),和4个字为空字符数组.创建现有字符串的子字符串只需"6"字,因为char数组是共享的.将一个Integer键和整数值成一个Hashtable需要64个字节(除Hashtable的数组中被预先分配的四个字节):我会让你明白为什么.
好吧,我显然尝试过,但我无法弄明白.在下面我只统计单词:Hashtable put创建一个Hashtable $ Entry:3(开销)+4个变量(3个引用,我假设是1个字+ 1个int).我还假设他意味着该整数被新分配的(因此不被Integer类缓存或已经存在),其涉及到2*(3 [开销] + 1 [1 int值]).
所以最后我们最终得到了15个字或60个字节.所以我首先想到的是,作为一个内部类的Entry需要引用它的外部对象,但是它是静态的,所以这没有多大意义(确定我们必须存储一个指向父类的指针,但我会认为信息由VM存储在类头中.
只是空闲的好奇心,我很清楚这一切都取决于实际的JVM实现(在64位版本上的结果会有所不同),但我仍然不喜欢我无法回答的问题:)
编辑:只是为了让这个更清楚一点:虽然我清楚地知道,更紧凑的结构可以让我们一些性能优势,我同意,在一般担心的几个字节在这里或那里是浪费时间.我肯定不会因为这里的几个字节开销而停止使用Hashtable,就像我不会使用普通字符数组而不是字符串(或开始使用C).学习更多关于Java/JVM内部的内容纯粹是学术上的兴趣:)
作者似乎假设 Map.Entry 中有 3 个对象,每个对象有 16 字节开销,有 2 个 32 位引用和 2 x 1 32 位int值。总共 64 字节
这是有缺陷的,因为 Sun/Oracle 的 JVM 仅在 8 字节边界上分配,因此虽然从技术上讲,整数占用 20 字节内存,但实际上使用了 24 字节(下一个 8 的倍数)
此外,许多 JVM 现在使用 64 位引用,因此 Map.Entry 将使用另外 16 个字节。
这都是非常低效的,这就是为什么您可能使用像 TIntIntHashMap 这样的类来代替使用基元的原因。
然而,通常这并不重要,因为与时间成本相比,内存非常便宜。如果您开发服务器应用程序,并且公司每小时的成本约为 40 美元,那么您需要每分钟节省大约 10 MB 的内存,才能节省与成本相当的内存。(理想情况下,您需要节省的比这多得多)每分钟节省 10 MB 是很困难的。
内存可以重复使用,但时间却不能。
| 归档时间: |
|
| 查看次数: |
673 次 |
| 最近记录: |