public abstract class MemoryManager
Manages memory assigned to key/value pairs. All byte arrays used in
keys/values should be allocated through this class - otherwise we risking
running out of java memory, and throw unexpected OutOfMemory errors. The
theory here is that *most* allocated bytes are allocated in large chunks by
allocating new Values - with large backing arrays. If we intercept these
allocation points, we cover most Java allocations. If such an allocation
might trigger an OOM error we first free up some other memory.
MemoryManager monitors memory used by the K/V store (by walking through the
store (see Cleaner) and overall heap usage by hooking into gc.
Memory is freed if either the cached memory is above the limit or if the
overall heap usage is too high (in which case we want to use less mem for
cache). There is also a lower limit on the amount of cache so that we never
delete all the cache and therefore some computation should always be able to
The amount of memory to be freed is determined as the max of cached mem above
the limit and heap usage above the limit.
One of the primary control inputs is FullGC cycles: we check heap usage and
set guidance for cache levels. We assume after a FullGC that the heap only
has POJOs (Plain Old Java Objects, unknown size) and K/V Cached stuff
(counted by us). We compute the free heap as MEM_MAX-heapUsage (after GC),
and we compute POJO size as (heapUsage - K/V cache usage).