In my code, which often runs on servers I do not control the configuration of, I have collection of users and each user has a byte[]
array.
Sometimes these byte[]
arrays are unique to the user. Often, though, there will be large numbers users with the exact same byte[]
array.
I am trying to reduce the RAM consumption of my server.
I've tried turning my byte[]
arrays into strings and interning them, but then I often run into PERM-GEN out-of-memory errors. I also see a significant performance degradation with the encoding/decoding when I want to access the byte[]
array for a user, and I see much increased worse-case memory usage - presuambly strings are much larger than arrays.
How can I have a Set<SoftReference<byte[]>>
lookup when Java arrays are not hashable and SoftReferences do not wrap the hash of the object the point at either. A Map<byte[],SoftReference<byte[]>>
is obviously also defeating itself because the key is itself and prevents collection; and Set
is internally implemented in terms of Map
anyway.
So how can I intern byte[]
arrays?
If you effectively have many identical arrays, use an HashSet<ByteBuffer>
as a cache. You can get the ByteBuffer array with method array()
and the ByteBuffer class has hashCode
and equals
methods. Of course it is better if your arrays are immutable.
EDIT2 The comment from @Will is exact, to be able to get back the array, use a WeakHashMap<ByteBuffer,WeakReference<ByteBuffer>>
and do something like that :
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();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With