Java hashmap,具有用于所有键的单字节[]数组

Java hashmap,具有用于所有键的单字节[]数组,java,arrays,hashmap,Java,Arrays,Hashmap,我有一个相当大的数据集,由2.3GB的数据组成,分布在1.6亿字节[]阵列上,平均数据长度为15字节。每个byte[]键的值只有一个int,因此hashmap的近一半(超过6GB)的内存使用量由每个字节数组的16字节开销组成 开销=8字节头+4字节长度,由VM向上取整为16字节 所以我的开销是2.5GB 有人知道hashmap实现将其(可变长度)字节[]键存储在一个大字节数组中,这样就不会有开销(除了1字节长度字段之外) 我宁愿不使用内存中的DB,因为与我正在使用的纯Trove-Tobjectn

我有一个相当大的数据集,由2.3GB的数据组成,分布在1.6亿字节[]阵列上,平均数据长度为15字节。每个byte[]键的值只有一个int,因此hashmap的近一半(超过6GB)的内存使用量由每个字节数组的16字节开销组成

开销=8字节头+4字节长度,由VM向上取整为16字节

所以我的开销是2.5GB

有人知道hashmap实现将其(可变长度)字节[]键存储在一个大字节数组中,这样就不会有开销(除了1字节长度字段之外)

我宁愿不使用内存中的DB,因为与我正在使用的纯Trove-TobjectnthAshmap相比,它们通常有性能开销,而且我更看重cpu周期,而不是内存使用


提前感谢

因为现在大多数个人电脑都有16GB,服务器通常是32-128GB或更高,所以一定程度的簿记开销真的有问题吗

如果我们考虑另一种选择:将字节数据连接到一个大数组中——我们应该考虑单个值看起来是什么样子,来引用一个更大的数组的一个片段。p> 通常情况下,您会从以下内容开始:

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*/}
}
这仍然是JVM对象头的5个字节(可能填充为8)。可能总共还是20个字节

似乎使用偏移量和长度解引用以及使用对象跟踪该偏移量和长度的成本并不比直接存储小数组的成本低多少

另一种理论上的可能性--取消映射键的结构,使其不是对象

可以设想对“长度和偏移量”数据进行解构,使其不再位于对象中。然后将其作为一组标量参数传递,例如(长度、偏移量),并且在hashmap实现中,将通过单独组件的数组(例如,而不是单个对象[]keyArray)进行存储

然而,我认为任何库都不太可能为您(非常特殊的)用例提供现有的hashmap实现

如果您谈论的是值,那么它可能毫无意义,因为Java不提供多个返回或方法输出参数;这使得如果不将结构化数据“装箱”回对象,通信就变得不切实际。既然这里你是专门询问地图键的,这些参数是作为参数传递的,但不需要返回,这样的方法在理论上是可以考虑的。 [扩展] 即使考虑到这一点,它也会变得很棘手——对于您的用例来说,MapAPI对于填充和查找可能会变得不对称,因为填充必须按(偏移量,len)定义键;然而,实际查找可能仍然是通过具体的byte[]数组


奥托:即使是很旧的笔记本电脑现在也有16GB。你写这篇文章的时间(需要维护4-10倍)应该比额外RAM的小成本要值钱得多。

数组没有实现equals()或hashCode(),你的Trove hashmap为你提供了这些吗?你为什么要使用
byte[]
作为hashmap的键?你使用的是什么JVM?我的印象是,如果
byte[]
的长度是奇数,那么开销将只有12个字节,因为整个结构被四舍五入到8的倍数。我用>new tobjectntcustomhashmap(new HashingStrategy()覆盖了equals()和hashCode(),我使用byte[],因为这就是我的数据,byte[]大小并不总是奇怪是的,我在考虑一个简单的get(int offset,byte len)问题,然后是散列函数,在不将数组划分为固定长度的“bucket”的情况下,如何找到将byte[]键转换为所有键的单个大byte[]数组中的偏移量这必须与最大密钥一样大,这样会浪费大量空间,因为平均密钥大小远小于最大密钥大小。我有32GB ram,但在处理过程中,我将剩余的内存用于其他数据(这需要解释),因此我需要节约内存使用量。