java.lang.Object | |
↳ | com.facebook.imagepipeline.memory.BasePool<V> |
Known Direct Subclasses |
Known Indirect Subclasses |
A base pool class that manages a pool of values (of type V).
The pool is organized as a map. Each entry in the map is a free-list (modeled by a queue) of entries for a given size. Some pools have a fixed set of buckets (aka bucketized sizes), while others don't.
The pool supports two main operations:
get(int)
- returns a value of size that's the same or larger than specified,
hopefully from the pool; otherwise, this value is allocated (via the alloc function)
release(V)
- releases a value to the pool
MemoryTrimmableRegistry
, and responds to
low-memory events (calls to trim). Some percent (perhaps all) of the values in the pool are then
released (via the underlying free function), and no longer belong to the pool.
Sizes There are 3 different notions of sizes we consider here (not all of them may be relevant for each use case).
Each concrete subclass of the pool must implement the following methods
getBucketedSize(int)
- returns the bucketized size for the given request size
getBucketedSizeForValue(Object)
- returns the bucketized size for a given value
getSizeInBytes(int)
- gets the size in bytes for a given bucketized size
alloc(int)
- allocates a value of given size
free(Object)
- frees the value V Subclasses may optionally implement
onParamsChanged()
- called whenever this class determines to re-read the pool
params
isReusable(Object)
- used to determine if a value can be reused or must be freed
InUse values The pool keeps track of values currently in use (in addition to the free values
in the buckets). This is maintained in an IdentityHashSet (using reference equality for the
values). The in-use set helps with accounting/book-keeping; we also use this during release(Object)
to avoid messing with (freeing/reusing) values that are 'unknown' to the pool.
PoolParams Pools are "configured" with a set of parameters (the PoolParams) supplied via a provider. This set of parameters includes
maxSizeSoftCap
The size of a pool includes its used and free space. The
maxSize setting for a pool is a soft cap on the overall size of the pool. A key point is
that get(int)
requests will not fail because the max size has been exceeded
(unless the underlying alloc(int)
function fails). However, the pool's free
portion will be trimmed as much as possible so that the pool's size may fall below the max
size. Note that when the free portion has fallen to zero, the pool may still be larger than
its maxSizeSoftCap. On a release(Object)
request, the value will be 'freed'
instead of being added to the free portion of the pool, if the pool exceeds its
maxSizeSoftCap. The invariant we want to maintain - see #ensurePoolSizeInvariant()
- is that the pool must be below the max size soft cap OR the free lists must be empty.
maxSizeHardCap
The hard cap is a stronger limit on the pool size. When
this limit is reached, we first attempt to trim the pool. If the pool size is still over
the hard, the get(int)
call will fail with a BasePool.PoolSizeViolationException
bucketSizes
The pool can be configured with a set of 'sizes' - a bucket
is created for each such size. Additionally, each bucket can have a a max-length specified,
which is the sum of the used and free items in that bucket. As with the MaxSize parameter
above, the maxLength here is a soft cap, in that it will not cause an exception on get; it
simply controls the release path. If the BucketSizes parameter is null, then the pool will
dynamically create buckets on demand.
Nested Classes | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
class | BasePool.InvalidSizeException | An exception to indicate that the requested size was invalid | |||||||||
class | BasePool.InvalidValueException | An exception to indicate if the 'value' is invalid. | |||||||||
class | BasePool.PoolSizeViolationException | Indicates that the pool size will exceed the hard cap if we allocated a value of size 'allocSize' | |||||||||
class | BasePool.SizeTooLargeException | A specific case of InvalidSizeException used to indicate that the requested size was too large |
Public Constructors | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
BasePool(MemoryTrimmableRegistry memoryTrimmableRegistry, PoolParams poolParams, PoolStatsTracker poolStatsTracker)
Creates a new instance of the pool.
| |||||||||||
BasePool(MemoryTrimmableRegistry memoryTrimmableRegistry, PoolParams poolParams, PoolStatsTracker poolStatsTracker, boolean ignoreHardCap) |
Public Methods | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
V |
get(int size)
Gets a new 'value' from the pool, if available.
| ||||||||||
synchronized Map<String, Integer> |
getStats()
Export memory stats regarding buckets used, memory caps, reused values.
| ||||||||||
void |
release(V value)
Releases the given value to the pool.
| ||||||||||
void |
trim(MemoryTrimType memoryTrimType)
Trims the pool in response to low-memory states (invoked from MemoryManager) For now, we'll do
the simplest thing, and simply clear out the entire pool.
|
Protected Methods | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
abstract V |
alloc(int bucketedSize)
Allocates a new 'value' with the given size
| ||||||||||
abstract void |
free(V value)
Frees the 'value'
| ||||||||||
abstract int |
getBucketedSize(int requestSize)
Gets the bucketed size (typically something the same or larger than the requested size)
| ||||||||||
abstract int |
getBucketedSizeForValue(V value)
Gets the bucketed size of the value
| ||||||||||
abstract int |
getSizeInBytes(int bucketedSize)
Gets the size in bytes for the given bucketed size
| ||||||||||
synchronized V | getValue(Bucket<V> bucket) | ||||||||||
void |
initialize()
Finish pool initialization.
| ||||||||||
boolean |
isReusable(V value)
Determines if the supplied value is 'reusable'.
| ||||||||||
void |
onParamsChanged()
The pool parameters may have changed.
|
[Expand]
Inherited Methods | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
From class
java.lang.Object
| |||||||||||
From interface
com.facebook.common.memory.MemoryTrimmable
| |||||||||||
From interface
com.facebook.common.memory.Pool
| |||||||||||
From interface
com.facebook.common.references.ResourceReleaser
|
Creates a new instance of the pool.
poolParams | pool parameters |
---|
Gets a new 'value' from the pool, if available. Allocates a new value if necessary. If we need
to perform an allocation, - If the pool size exceeds the max-size soft cap, then we attempt to
trim the free portion of the pool. - If the pool size exceeds the max-size hard-cap (after
trimming), then we throw an BasePool.PoolSizeViolationException
Bucket length constraints are
not considered in this function
size | the logical size to allocate |
---|
Export memory stats regarding buckets used, memory caps, reused values.
Releases the given value to the pool. In a few cases, the value is 'freed' instead of being released to the pool. If - the pool currently exceeds its max size OR - if the value does not map to a bucket that's currently maintained by the pool, OR - if the bucket for the value exceeds its maxLength, OR - if the value is not recognized by the pool then, the value is 'freed'.
value | the value to release to the pool |
---|
Trims the pool in response to low-memory states (invoked from MemoryManager) For now, we'll do the simplest thing, and simply clear out the entire pool. We may consider more sophisticated approaches later. In other words, we ignore the memoryTrimType parameter
memoryTrimType | the kind of trimming we want to perform |
---|
Allocates a new 'value' with the given size
bucketedSize | the logical size to allocate |
---|
Frees the 'value'
value | the value to free |
---|
Gets the bucketed size (typically something the same or larger than the requested size)
requestSize | the logical request size |
---|
if the size of the value doesn't match the pool's constraints |
Gets the bucketed size of the value
value | the value |
---|
if the size of the value doesn't match the pool's constraints | |
if the value is invalid |
Gets the size in bytes for the given bucketed size
bucketedSize | the bucketed size |
---|
Finish pool initialization.
Determines if the supplied value is 'reusable'. This is called during release(Object)
,
and determines if the value can be added to the freelists of the pool (for future reuse), or
must be released right away. Subclasses can override this to provide custom implementations
value | the value to test for reusability |
---|
The pool parameters may have changed. Subclasses can override this to update any state they were maintaining