创建字节数组的缓存

2022-09-04 04:08:02

在我的代码中,它经常在我无法控制的服务器上运行,我有用户的集合,每个用户都有一个数组。byte[]

有时,这些数组对于用户是唯一的。但是,通常会有大量用户使用完全相同的数组。byte[]byte[]

我正在尝试减少服务器的 RAM 消耗。

我尝试过将数组转换为字符串并实习它们,但后来我经常遇到PERM-GEN内存不足错误。当我想为用户访问数组时,我还看到编码/解码的性能显着下降,并且我看到更糟糕的内存使用率大大增加 - 预先说服的字符串比数组大得多。byte[]byte[]

当Java数组不可哈希并且SoftReferences不将对象的哈希包装在点上时,我怎么能进行查找。A显然也在打败自己,因为钥匙是它自己,阻止了收集;并且无论如何都在内部实现。Set<SoftReference<byte[]>>Map<byte[],SoftReference<byte[]>>SetMap

那么,如何才能实习阵列呢?byte[]


答案 1

如果实际上有许多相同的数组,请使用 用作缓存。您可以获取带有方法的 ByteBuffer 数组,而 ByteBuffer 类具有 and 方法。当然,如果您的数组是不可变的,那就更好了。HashSet<ByteBuffer>array()hashCodeequals

编辑2来自@Will的注释是准确的,以便能够取回数组,使用a并执行类似操作:WeakHashMap<ByteBuffer,WeakReference<ByteBuffer>>

public byte[] internalize(byte[] bytes) {
 ByteBuffer wrapped = ByteBuffer.wrap(bytes);
 if(cache.containsKey(wrapped)) {
  wrapped = cache.get(wrapped).get();
 }
 else {
  cache.put(wrapped, new WeakReference<ByteBuffer>(wrapped);
 }
 return wrapped.array();
}

答案 2

我尝试过将我的byte[]数组转换为字符串并插入它们,但后来我经常遇到PERM-GEN内存不足错误。

我同意你需要类似的东西,但标准实现是,所以没有太多的喜悦。String.intern()native

您可以使用字节数组的哈希代码作为键来设置 。然后,您的方法可以使用与给定字节数组相同的有代码查找现有字节数组的集合。使用一个好的哈希代码,应该给出一小组数组来检查匹配项。Map<Integer,Collection<SoftReference<byte[]>>>Mapintern


编辑:澄清:

像这样:

 class ByteArrayCache
 {
      private final Map<Integer,Collection<SoftReference<byte[]>> map = new ...;

      public final byte[] intern(byte[] byteArray)
      {
           final int hash = Arrays.hashCode(byteArray);
           final Collection<SoftReference<byte[]>> arrays = map.get(hash);
           if (arrays != null) {
              // Search through arrays for a match, and return the match.
              // If no match found, add byteArray to the collection and return it
           } else {
              // create a new map entry, add byteArray to it, and return byte array
           }
      }
 }