Add DiscardableMemoryAllocator to minimize use of FDs with discardable memory.
Discardable memory has the current limitation on Android (at least) that it's
backed by a file (descriptor) thus it is a limited resource.
DiscardableMemoryAllocator provides a way to create instances of
DiscardableMemory in an efficient way. Note that just like regular
DiscardableMemory, the DiscardableMemoryAllocator should not be used for small
allocations since it works with page granularity (4 KBytes).
On Android DiscardableMemory creation can now happen in two different ways:
- Each client-requested allocation is backed by an individual ashmem region.
This allows to delete ashmem regions individually by closing the ashmem file
descriptor. This is the default path that is taken when file descriptor usage
allows us to do so.
- Allocations are performed by the global allocator when file descriptor usage
gets too high. This still allows unpinning but does not allow deleting
individual regions (i.e. immediately releasing the physycal pages backing
them). Unfortunately the physical memory backing an ashmem region is only
freed when the file descriptor is closed.
madvise(MADV_REMOVE)/fallocate(FALLOCATE_FL_PUNCH_HOLE) don't work with
ashmem unfortunately.
When file descriptor usage gets too high (which can be observed on
images.google.com for instance) the allocator starts operating by creating as
less ashmem regions (= consuming as less FDs) as possible:
- Large (32 MBytes) ashmem regions get lazily created. This size might need
some tuning/runtime adjustment as a follow up.
- Allocation works first by trying to recycle previously freed chunks (if any)
by doing a closest size match (implemented with multiset<>.lower_bound() in
O(log n)).
If no free chunks can be recycled then a new chunk in the ashmem region is
returned to the user. If the ashmem region is not big enough then a new
region is created.
- DiscardableMemory instance deletion works by marking the chunk used by the
instance as discardable (i.e. ashmem_region_unpin()) and notifying the
allocator with the metadata (e.g. chunk size) that allows it to later recycle
the chunk efficiently.
Note that free chunks are marked as discardable as mentioned above therefore
they can be reclaimed by the kernel under memory pressure. Since they are not
immediately released unfortunately the allocator still tries to minimize
fragmentation (to avoid causing memory pressure) by merging free contiguous
chunks when possible as well as splitting recycled free chunks that are too
large (and that would cause fragmentation).
BUG=299828
Review URL: https://codereview.chromium.org/25293002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@239763 0039d316-1c4b-4281-b951-d872f2087c98
CrOS-Libchrome-Original-Commit: e3fc9dab67bdf403b487e4b9d7c1dc8f6263903e
9 files changed