[英]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類具有hashCode
和equals
方法。 當然,如果你的數組是不可變的,那就更好了。
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.