簡體   English   中英

創建字節數組的緩存

[英]creating a cache of byte arrays

在我的代碼中,它通常在服務器上運行,我不控制配置,我有用戶集合,每個用戶都有一個byte[]數組。

有時這些byte[]數組對用戶來說是唯一的。 但是,通常會有大量用戶使用完全相同的byte[]數組。

我試圖減少我的服務器的RAM消耗。

我已經嘗試將我的byte[]數組轉換為字符串並實習它們,但后來我經常遇到PERM-GEN內存不足錯誤。 當我想為用戶訪問byte[]數組時,我也發現編碼/解碼會導致顯着的性能下降,而且我看到更糟糕的內存使用情況 - 預備字符串比數組大得多。

當Java數組不可清除時,如何使用Set<SoftReference<byte[]>>查找,而SoftReferences不會將對象的哈希值包裝在任何一個點上。 Map<byte[],SoftReference<byte[]>>顯然也會使自己失敗,因為密鑰本身並阻止了收集; Set來講是內部實現Map反正。

那我怎么能實習 byte[]數組呢?

如果您有效地擁有許多相同的數組,請使用HashSet<ByteBuffer>作為緩存。 您可以使用方法array()獲取ByteBuffer數組,並且ByteBuffer類具有hashCodeequals方法。 當然,如果你的數組是不可變的,那就更好了。

EDIT2來自@Will的評論是准確的,為了能夠取回數組,使用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();
}

我已經嘗試將我的byte []數組轉換為字符串並實習它們,但后來我經常遇到PERM-GEN內存不足錯誤。

我同意你需要像String.intern()這樣的東西,但是標准的實現是native ,所以沒有多少快樂。

你可以使用Map<Integer,Collection<SoftReference<byte[]>>> ,使用字節數組的哈希碼作為Map鍵。 然后,您的intern方法可以使用與給定字節數組相同的代碼查找現有字節數組。 使用一個好的哈希代碼,它應該提供一小組數組來檢查匹配。


編輯:澄清:

像這樣的東西:

 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
           }
      }
 }

我會基於Guava弱值映射實現緩存。 它保證如果沒有對字節數組的更強引用,則會自動刪除該條目。

class Cache {
    private final ConcurrentMap<Key, byte[]> map = new MapMaker().weakValues().makeMap();

    private static class Key {
        byte[] a;
        int hash;

        Key(byte[] a) {
            this.a = a;
            hash = Arrays.hashCode(a);
        }

        @Override
        public int hashCode() {
            return hash;
        }

        @Override
        public boolean equals(Object obj) {
            if (obj instanceof Key) {
                return Arrays.equals(a, ((Key) obj).a);
            }
            return false;
        }
    }

    public byte[] intern(byte[] a) {
        byte[] a1 = map.putIfAbsent(new Key(a), a);
        if (a1 != null) {
            return a1; 
        }
        return a;
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM