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
tree: e485bb57d4b443e23553154e0a3584dce6ed6254
  1. base/
  2. build/
  3. components/
  4. dbus/
  5. ipc/
  6. mojo/
  7. testing/
  8. third_party/
  9. ui/