假设我正在哈希表中存储1000个对象。该哈希表已扩展,可以将三维坐标映射到其中存储的对象;内部的对象有固定大小。哈希键是一个长整型数。
如何通过数学方法计算出此结构的可能开销?
1.如果内部数据约为256MB,它的开销是否足够显著? 2.除了使用代码分析器外(在某些情况下不可靠),是否有一种可靠的方法来计算其开销应该是多少?
我对哈希表的总大小不感兴趣 - 只关心使用哈希表会产生的开销。例如,如果我有10个int类型,每个占用4个字节,则是40个字节。如果我将它们放入数组中,我得到12个字节的恒定开销- 8个用于对象头,4个用于长度。如果我将它们放入另一个结构(例如TreeSet)中,我的开销将不是恒定的,因为树需要节点-因此我可能会得到以n表示的开销,其中n是集合中的项目数。
这里有一些对我来说很明显的事情,我将从这里开始:
1. 我将至少需要存储1000个longs。这些是可空类型,因此它们实际上是对象。因此,我假设正在使用的8字节长整型具有8字节的对象头。我将添加一个16n的因子。 2. 我还需要对每个对象进行引用,这些引用必须存在,无论对象是否已从映射中召回并正在使用。因此,每个对象需要额外的8字节。我们可以将其纳入数据大小中,但由于引用位于哈希表本身中,所以我认为最好将其作为开销的一部分。我的逻辑是:如果我取出哈希表中的所有数据并将它们存储在变量中,则那些n个引用仍将存在于哈希表中,前提是我没有删除这些数据对象,而我不会这样做。对象集是恒定的,尽管可以使用不同的键对其进行回收。 3. 哈希表本身的开销为8字节。 4. 哈希表必须存储内部项数(或者我认为如此!),因此需要4个字节。 5. 我愚蠢地假设哈希键位于数组中,并按哈希键顺序排序。该数组需要12个字节。 6. 我还假设对象也位于匹配数组中,并且在找到键时将其取消引用。我猜测另外需要12个字节。
这让我得到一个多项式方程:36 + 24n。
因此,我猜测使用长键的1000个数据对象的开销为24036字节。这是一种微不足道的开销,但我的问题是,实际开销是多少呢?
第二个有效的问题是,这在不同的JVM上有多大差异?有没有一种与JVM无关的方法来解决这个问题?举个例子,考虑一个只有32位对象头的JVM - 当查看数组时,你可能会说,即使大小因JVM而异,但在这种情况下,数组的开销将变为8个字节而不是12个字节。
我假设HashMap在相同版本的Java中采用固定的实现方式。
我可以尝试阅读源代码或运行分析,但这可能会产生基于我的JVM的误导性结果。我请求您的帮助 - 也许是了解情况的人 - 获得一些我们都不知道的信息。谢谢!
请参见以下答案,实际估计可以表示为:
每个条目8个字,加上每个长整型8个字节,再加上哈希映射对象头8个字节。
在我目前的环境(32位操作系统)中,1个字=4个字节。
如何通过数学方法计算出此结构的可能开销?
1.如果内部数据约为256MB,它的开销是否足够显著? 2.除了使用代码分析器外(在某些情况下不可靠),是否有一种可靠的方法来计算其开销应该是多少?
我对哈希表的总大小不感兴趣 - 只关心使用哈希表会产生的开销。例如,如果我有10个int类型,每个占用4个字节,则是40个字节。如果我将它们放入数组中,我得到12个字节的恒定开销- 8个用于对象头,4个用于长度。如果我将它们放入另一个结构(例如TreeSet)中,我的开销将不是恒定的,因为树需要节点-因此我可能会得到以n表示的开销,其中n是集合中的项目数。
这里有一些对我来说很明显的事情,我将从这里开始:
1. 我将至少需要存储1000个longs。这些是可空类型,因此它们实际上是对象。因此,我假设正在使用的8字节长整型具有8字节的对象头。我将添加一个16n的因子。 2. 我还需要对每个对象进行引用,这些引用必须存在,无论对象是否已从映射中召回并正在使用。因此,每个对象需要额外的8字节。我们可以将其纳入数据大小中,但由于引用位于哈希表本身中,所以我认为最好将其作为开销的一部分。我的逻辑是:如果我取出哈希表中的所有数据并将它们存储在变量中,则那些n个引用仍将存在于哈希表中,前提是我没有删除这些数据对象,而我不会这样做。对象集是恒定的,尽管可以使用不同的键对其进行回收。 3. 哈希表本身的开销为8字节。 4. 哈希表必须存储内部项数(或者我认为如此!),因此需要4个字节。 5. 我愚蠢地假设哈希键位于数组中,并按哈希键顺序排序。该数组需要12个字节。 6. 我还假设对象也位于匹配数组中,并且在找到键时将其取消引用。我猜测另外需要12个字节。
这让我得到一个多项式方程:36 + 24n。
因此,我猜测使用长键的1000个数据对象的开销为24036字节。这是一种微不足道的开销,但我的问题是,实际开销是多少呢?
第二个有效的问题是,这在不同的JVM上有多大差异?有没有一种与JVM无关的方法来解决这个问题?举个例子,考虑一个只有32位对象头的JVM - 当查看数组时,你可能会说,即使大小因JVM而异,但在这种情况下,数组的开销将变为8个字节而不是12个字节。
我假设HashMap在相同版本的Java中采用固定的实现方式。
我可以尝试阅读源代码或运行分析,但这可能会产生基于我的JVM的误导性结果。我请求您的帮助 - 也许是了解情况的人 - 获得一些我们都不知道的信息。谢谢!
请参见以下答案,实际估计可以表示为:
每个条目8个字,加上每个长整型8个字节,再加上哈希映射对象头8个字节。
在我目前的环境(32位操作系统)中,1个字=4个字节。
- 在32位环境中的40n + 8:1000个条目的开销约为40k
- 在64位环境中的72n + 8:1000个条目的开销约为72k。