我有一个相当大的数据集,包含2.3GB的数据,分布在1.6亿个byte []数组中,平均数据长度为15个字节。每个byte []键的值只是一个int,所以几乎一半的hashmap(超过6GB)的内存使用量由每个字节数组的16字节开销组成
开销= 8字节标头+ 4字节长度由VM向上舍入到16字节。
所以我的开销是2.5GB。
是否有人知道将(可变长度)byte []键存储在一个大字节数组中的hashmap实现,因此不会有开销(除1个字节长度的字段外)?
我宁愿不使用内存数据库,因为与我正在使用的普通Trove TObjectIntHashMap相比,它们通常具有性能开销,我更重视CPU周期,甚至超过内存使用量。
提前致谢
答案 0 :(得分:2)
由于目前大多数个人计算机的容量为16GB,而服务器的容量通常为32 - 128 GB或更高,因此存在一定程度的簿记开销存在问题吗?
如果我们考虑替代方案:字节数据连接成一个大型数组 - 我们应该考虑单个值看起来像什么,以引用更大数组的切片。
一般来说,你会从:
开始public class ByteSlice {
protected byte[] array;
protected int offset;
protected int len;
}
然而,那8个字节+指针的大小(可能只有4个字节?)+ JVM对象头(64位JVM上的12个字节)。所以也许总共24个字节。
如果我们尝试制作这个单一用途的&极简主义者,我们仍然需要4个字节的偏移量。
public class DedicatedByteSlice {
protected int offset;
protected byte len;
protected static byte[] getArray() {/*somebody else knows about the array*/}
}
这仍然是5个字节(可能填充到8个)+ JVM对象头。可能仍然总共20个字节。
看起来用偏移量和放大器解除引用的成本。长度,并有一个跟踪它的对象,并不比直接存储小阵列的成本低。
另一个理论上的可能性 - 解析Map Key以使其不是对象
可以设想解构"长度&偏移"数据使其不再存在于对象中。然后它作为一组标量参数传递,例如(长度,偏移),并且 - 在散列图实现中 - 将通过单独组件的数组(例如,而不是单个Object [] keyArray)存储。
但是我希望任何库都不太可能为你的(非常特殊的)用例提供现有的hashmap实现。
如果你在讨论值,它可能毫无意义,因为Java不提供多个返回或方法OUT参数;没有"拳击"这使得沟通变得不切实际。将结构化数据返回给对象。因为在这里你要专门询问地图关键字,并且它们作为参数传递但不需要返回,理论上可以考虑这种方法。
<强> [扩展] 强> 即使考虑到这一点,它变得棘手 - 对于你的用例,地图API可能必须变得不对称的人口与查找,因为人口必须通过(偏移,len)来定义密钥;实际查找可能仍然是由具体的byte []数组。
OTOH:即使是相当旧的笔记本电脑也有16GB。你写这篇文章的时间(维持4到10倍)应该远远超过额外RAM的小成本。