[sanitizer] Change the 32-bit Primary AllocateRegion to reduce fragmentation
authorKostya Kortchinsky <kostyak@google.com>
Thu, 25 May 2017 16:19:57 +0000 (16:19 +0000)
committerKostya Kortchinsky <kostyak@google.com>
Thu, 25 May 2017 16:19:57 +0000 (16:19 +0000)
commit0dd40cf28d2ea2a8b18a1379a10019f343c51d74
treef250c7266acc3ba80cdb47b11855f416766e5d4b
parent76886e82e580339fe5638defb522f7ca8a6ec1e2
[sanitizer] Change the 32-bit Primary AllocateRegion to reduce fragmentation

Summary:
Currently, AllocateRegion has a tendency to fragment memory: it allocates
`2*kRegionSize`, and if the memory is aligned, will unmap `kRegionSize` bytes,
thus creating a hole, which can't itself be reused for another region. This
is exacerbated by the fact that if 2 regions get allocated one after another
without any `mmap` in between, the second will be aligned due to mappings
generally being contiguous.

An idea, suggested by @alekseyshl, to prevent such a behavior is to have a
stash of regions: if the `2*kRegionSize` allocation is properly aligned, split
it in two, and stash the second part to be returned next time a region is
requested.

At this point, I thought about a couple of ways to implement this:
 - either an `IntrusiveList` of regions candidates, storing `next` at the
   begining of the region;
 - a small array of regions candidates existing in the Primary.

While the second option is more constrained in terms of size, it offers several
advantages:
 - security wise, a pointer in a region candidate could be overflowed into, and
   abused when popping an element;
 - we do not dirty the first page of the region by storing something in it;
 - unless several threads request regions simultaneously from different size
   classes, the stash rarely goes above 1 entry.

I am not certain about the Windows impact of this change, as `sanitizer_win.cc`
has its own version of MmapAlignedOrDie, maybe someone could chime in on this.

MmapAlignedOrDie is effectively unused after this change and could be removed
at a later point. I didn't notice any sizeable performance gain, even though we
are saving a few `mmap`/`munmap` syscalls.

Reviewers: alekseyshl, kcc, dvyukov

Reviewed By: alekseyshl

Subscribers: llvm-commits, kubamracek

Differential Revision: https://reviews.llvm.org/D33454

llvm-svn: 303879
compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary32.h