2014-04-07 23:54:11 +00:00
|
|
|
/*
|
2018-04-10 23:34:42 +00:00
|
|
|
* Copyright (C) 2014-2018 Apple Inc. All rights reserved.
|
2014-04-07 23:54:11 +00:00
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
|
|
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
|
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
|
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
|
|
|
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
2016-03-15 05:39:35 +00:00
|
|
|
#ifndef SmallPage_h
|
|
|
|
#define SmallPage_h
|
2014-04-07 23:54:11 +00:00
|
|
|
|
2016-02-20 01:06:49 +00:00
|
|
|
#include "BAssert.h"
|
2016-03-08 21:21:38 +00:00
|
|
|
#include "List.h"
|
2016-02-20 01:06:49 +00:00
|
|
|
#include "Mutex.h"
|
|
|
|
#include "VMAllocate.h"
|
|
|
|
#include <mutex>
|
2014-04-07 23:54:11 +00:00
|
|
|
|
|
|
|
namespace bmalloc {
|
|
|
|
|
2017-06-24 20:14:33 +00:00
|
|
|
class SmallLine;
|
|
|
|
|
2016-03-15 05:39:35 +00:00
|
|
|
class SmallPage : public ListNode<SmallPage> {
|
2016-02-20 01:06:49 +00:00
|
|
|
public:
|
2020-01-18 00:43:00 +00:00
|
|
|
void ref(UniqueLockHolder&);
|
|
|
|
bool deref(UniqueLockHolder&);
|
|
|
|
unsigned refCount(UniqueLockHolder&) { return m_refCount; }
|
2019-02-12 19:20:51 +00:00
|
|
|
|
2016-02-20 01:06:49 +00:00
|
|
|
size_t sizeClass() { return m_sizeClass; }
|
|
|
|
void setSizeClass(size_t sizeClass) { m_sizeClass = sizeClass; }
|
|
|
|
|
2020-01-18 00:43:00 +00:00
|
|
|
bool hasFreeLines(UniqueLockHolder&) const { return m_hasFreeLines; }
|
|
|
|
void setHasFreeLines(UniqueLockHolder&, bool hasFreeLines) { m_hasFreeLines = hasFreeLines; }
|
2016-02-20 01:06:49 +00:00
|
|
|
|
bmalloc: Small and large objects should share memory
https://bugs.webkit.org/show_bug.cgi?id=172880
<rdar://problem/31494732>
Reviewed by Sam Weinig.
This reduces our high water mark memory usage on JetStream on macOS
by 10%-20%. It also has the nice side effect that we can free small
object metadata after returning from a high water mark.
No change in throughput.
Our old algorithm allocated small object chunks and large objects in
segregated virtual memory and never recycled addresses between them.
This provided a slight security benefit because we could apply guard
pages between the segregated ranges and we would never reuse the same
virtual address for object and metadata memory.
Our new algorithm allocates small object chunks from the large object
allocator. This naturally recycles memory between small chunks and large
objects, and between small chunks of different page classes. This allows
us to shift memory between allocation types as a program moves between
different phases of allocation, and to delete small object chunk metadata
when a program shrinks back from a high water mark.
Two intuitions I had about memory use turned out to be backwards in
this context:
(1) I thought that this optimization would work because it allowed you to
allocate and free a 4MB object and then reuse that large allocation to
service small allocations. In practice, the common benefit seems to be
the opposite: After you allocate and free many small objects, you can
stitch them together to allocate a large object without growing the heap.
(2) I thought that it would be more memory-efficient to allocate
fine-grained pages from the large object allocator. In practice, giving
the large object allocator too many arbitrarily-sized ranges to manage
leads to fragmentation. Meanwhile, segregated fit is a powerful memory
optimization. So, it's best to return small object memory to the large
allocator only when a whole small object chunk is free.
* bmalloc/Chunk.h:
(bmalloc::Chunk::ref):
(bmalloc::Chunk::deref):
(bmalloc::Chunk::refCount):
(bmalloc::Chunk::freePages): We keep a free list per chunk and refcount
each chunk so we can notice when a chunk becomes empty, and return it
to the large allocator.
(bmalloc::forEachPage): A new helper function for iterating the pages
in a Chunk.
(bmalloc::Chunk::Chunk): Use forEachPage instead of manual iteration.
Use { } initialization because we don't get zero-initialized by the OS
anymore.
* bmalloc/Heap.cpp:
(bmalloc::Heap::Heap):
(bmalloc::Heap::concurrentScavenge):
(bmalloc::Heap::scavenge): Don't bother unlocking while scavenging. I
wasn't able to show it to be a consistent speedup. A more promising
approach, if we find a motivating example, is for the scavenger to give
up and return early if any other client is waiting on the lock.
(bmalloc::Heap::allocateSmallChunk): New helper function for allocating
a small chunk. It allocates through the large allocator to facilitate
sharing. We still allocate a chunk at a time instead of a page at a time.
Surprisingly, more precise page-at-a-time allocation is worse for memory
use because of fragmentation. Segregated fit is a powerful optimization.
(bmalloc::Heap::deallocateSmallChunk): New helper function for deallocating
a small chunk.
(bmalloc::Heap::allocateSmallPage): Updated for new APIs.
(bmalloc::Heap::deallocateSmallLine): Updated for new APIs. Note that
we cache one free chunk per page class. This avoids churn in the large
allocator when you free(malloc(X)).
(bmalloc::Heap::allocateSmallBumpRangesByMetadata):
(bmalloc::Heap::allocateSmallBumpRangesByObject):
(bmalloc::Heap::tryAllocateLarge):
(bmalloc::Heap::scavengeSmallPages): Deleted.
(bmalloc::Heap::scavengeLargeObjects): Deleted.
* bmalloc/Heap.h:
* bmalloc/LargeMap.h:
(bmalloc::LargeMap::begin):
(bmalloc::LargeMap::end): Added iteration helpers for scavenging.
* bmalloc/LargeRange.h:
(bmalloc::LargeRange::physicalSize): Added a comment about something
that I confused myself about in this patch.
* bmalloc/List.h:
(bmalloc::List::iterator::operator*):
(bmalloc::List::iterator::operator->):
(bmalloc::List::iterator::operator!=):
(bmalloc::List::iterator::operator++):
(bmalloc::List::begin):
(bmalloc::List::end):
(bmalloc::List::pushFront):
(bmalloc::List::remove):
(bmalloc::ListNode::ListNode): Deleted. Added iteration helpers for
scavenging. Changed the default state of a Node to null pointers instead
of self pointers to distinguish the null node from the empty node for
easier debugging.
* bmalloc/Sizes.h: Changed the chunk size to 1MB to increase the chances
of a chunk becoming free and recyclable.
* bmalloc/SmallPage.h:
(bmalloc::SmallPage::hasPhysicalPages):
(bmalloc::SmallPage::setHasPhysicalPages): Track physical state by page
instead of implicitly by which list a page is in. It's simpler not
to have to move chunks and pages between physical vs virtual lists.
(bmalloc::SmallPage::SmallPage): Deleted.
* bmalloc/VMHeap.cpp:
(bmalloc::VMHeap::tryAllocateLargeChunk):
(bmalloc::VMHeap::allocateSmallChunk): Deleted.
* bmalloc/VMHeap.h:
(bmalloc::VMHeap::allocateSmallPage): Deleted.
(bmalloc::VMHeap::deallocateSmallPage): Deleted. Small chunk allocation
just forwards to the large allocator now.
* bmalloc/bmalloc.h:
(bmalloc::api::scavenge):
Canonical link: https://commits.webkit.org/189836@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@217811 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-06-06 02:21:11 +00:00
|
|
|
bool hasPhysicalPages() { return m_hasPhysicalPages; }
|
|
|
|
void setHasPhysicalPages(bool hasPhysicalPages) { m_hasPhysicalPages = hasPhysicalPages; }
|
2019-09-09 22:38:40 +00:00
|
|
|
|
[BMalloc] Scavenger should react to recent memory activity
https://bugs.webkit.org/show_bug.cgi?id=195895
Reviewed by Geoffrey Garen.
This change adds a recently used bit to objects that are scavenged. When an object is allocated, that bit is set.
When we scavenge, if the bit is set, we clear it. If the bit was already clear, we decommit the object. The timing
to scavenging has been changed as well. We perform our first scavne almost immediately after bmalloc is initialized
(10ms later). Subsequent scavenging is done as a multiple of the time it took to scavenge. We bound this computed
time between a minimum and maximum. Through empirical testing, the multiplier, minimum and maximum are
150x, 100ms and 10,000ms respectively. For mini-mode, when the JIT is disabled, we use much more aggressive values of
50x, 25ms and 500ms.
Eliminated partial scavenging since this change allows for any scavenge to be partial or full based on recent use of
the objects on the various free lists.
* bmalloc/Chunk.h:
(bmalloc::Chunk::usedSinceLastScavenge):
(bmalloc::Chunk::clearUsedSinceLastScavenge):
(bmalloc::Chunk::setUsedSinceLastScavenge):
* bmalloc/Heap.cpp:
(bmalloc::Heap::scavenge):
(bmalloc::Heap::allocateSmallChunk):
(bmalloc::Heap::allocateSmallPage):
(bmalloc::Heap::splitAndAllocate):
(bmalloc::Heap::tryAllocateLarge):
(bmalloc::Heap::scavengeToHighWatermark): Deleted.
* bmalloc/Heap.h:
* bmalloc/IsoDirectory.h:
* bmalloc/IsoDirectoryInlines.h:
(bmalloc::passedNumPages>::takeFirstEligible):
(bmalloc::passedNumPages>::scavenge):
(bmalloc::passedNumPages>::scavengeToHighWatermark): Deleted.
* bmalloc/IsoHeapImpl.h:
* bmalloc/IsoHeapImplInlines.h:
(bmalloc::IsoHeapImpl<Config>::scavengeToHighWatermark): Deleted.
* bmalloc/LargeRange.h:
(bmalloc::LargeRange::LargeRange):
(bmalloc::LargeRange::usedSinceLastScavenge):
(bmalloc::LargeRange::clearUsedSinceLastScavenge):
(bmalloc::LargeRange::setUsedSinceLastScavenge):
(): Deleted.
* bmalloc/Scavenger.cpp:
(bmalloc::Scavenger::Scavenger):
(bmalloc::Scavenger::threadRunLoop):
(bmalloc::Scavenger::timeSinceLastPartialScavenge): Deleted.
(bmalloc::Scavenger::partialScavenge): Deleted.
* bmalloc/Scavenger.h:
* bmalloc/SmallPage.h:
(bmalloc::SmallPage::usedSinceLastScavenge):
(bmalloc::SmallPage::clearUsedSinceLastScavenge):
(bmalloc::SmallPage::setUsedSinceLastScavenge):
Canonical link: https://commits.webkit.org/210213@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@243144 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-03-19 17:31:01 +00:00
|
|
|
bool usedSinceLastScavenge() { return m_usedSinceLastScavenge; }
|
|
|
|
void clearUsedSinceLastScavenge() { m_usedSinceLastScavenge = false; }
|
|
|
|
void setUsedSinceLastScavenge() { m_usedSinceLastScavenge = true; }
|
|
|
|
|
2016-02-20 01:06:49 +00:00
|
|
|
SmallLine* begin();
|
|
|
|
|
2016-03-30 02:22:47 +00:00
|
|
|
unsigned char slide() const { return m_slide; }
|
|
|
|
void setSlide(unsigned char slide) { m_slide = slide; }
|
bmalloc: segregate small and large objects again, and allocate more objects on the small path
https://bugs.webkit.org/show_bug.cgi?id=156152
Reviewed by Sam Weinig.
Microbenchmark data suggested that it was a good idea for small and large
objects to share memory. But r198675 did not improve memory use in
full browser benchmarks.
This patch reverts to segregating small and large objects -- but without
going back to doubled VM usage -- in order to capture a few benefits:
(*) Small pages fragment the large heap. Separating them out saves a lot
of memory in our worst case fragmentation recording:
nimlang 276,076kB 209,636kB ^ 1.32x smaller
(*) Small objects are common enough that even their slow paths benefit
from simpler code:
Execution Time:
...
facebook 234ms 216ms ^ 1.08x faster
reddit 114ms 108ms ^ 1.06x faster
flickr 118ms 111ms ^ 1.06x faster
theverge 146ms 140ms ^ 1.04x faster
...
<arithmetic mean> 107ms 102ms ^ 1.04x faster
(*) We can use less metadata:
Memory at End:
...
list_allocate 460kB 384kB ^ 1.2x smaller
tree_allocate 492kB 424kB ^ 1.16x smaller
tree_churn 480kB 404kB ^ 1.19x smaller
fragment 532kB 452kB ^ 1.18x smaller
fragment_iterate 712kB 588kB ^ 1.21x smaller
medium 15,152kB 11,796kB ^ 1.28x smaller
big 15,044kB 10,976kB ^ 1.37x smaller
...
<arithmetic mean> 7,724kB 7,190kB ^ 1.07x smaller
This patch also takes advantage of our support for varying the page size
at runtime by allocating more objects on the small object path:
medium 178ms 150ms ^ 1.19x faster
Some microbenchmarks report memory use increases from this change -- like
they reported memory use decreases from r198675 -- but I'm ignoring them
for now because I expect our full browser memory benchmarks to confirm
that this patch is fine.
* bmalloc/BumpAllocator.h:
(bmalloc::BumpAllocator::BumpAllocator): Use a full unsigned because we
can allocate objects larger than 16kB - 1, and a full unsigned does not
make BumpAllocator any larger on 64bit systems.
* bmalloc/Chunk.h:
(bmalloc::Chunk::begin):
(bmalloc::Chunk::end):
(bmalloc::Chunk::size):
(bmalloc::Chunk::objectType): Store ObjectType in the Chunk, since it only
varies by Chunk now, and not from page to page within a Chunk. Also,
union together small and large object metadata, since we will only use
one or the other. This saves memory.
(bmalloc::Chunk::Chunk): Conditionalize initialization based on object
type, since only one kind of metadata or the other can be used at runtime.
(bmalloc::Object::Object):
(bmalloc::Object::begin):
(bmalloc::SmallPage::end): Deleted.
* bmalloc/Heap.cpp:
(bmalloc::Heap::Heap):
(bmalloc::Heap::initializeLineMetadata): Save a little space, since we
know that lines are only 256 bytes long.
(bmalloc::Heap::initializePageMetadata): Store a dynamic page size for
each size class. We used to use only one page size (the system page size)
but that limited our ability to allocate objects larger than 1kB on the
small object path. Now we can handle any object size we want by storing
objects of that size in a custom page size.
(bmalloc::Heap::concurrentScavenge):
(bmalloc::Heap::scavenge):
(bmalloc::Heap::scavengeSmallPages): Revert to our old linked list
strategy for storing small pages.
(bmalloc::Heap::splitAndAllocate): Object type is per Chunk now.
(bmalloc::Heap::allocateLarge): Don't nuke the small page list when
allocating a large object because the two don't share memory anymore.
(bmalloc::Heap::allocateSmallPage): Revert to our old linked list
strategy for storing small pages.
(bmalloc::Heap::deallocateSmallLine): Don't return early in the case
where this is the first free object in the page. In the case of large-ish
objects, the first free object might also be the last free object,
since there's one object per page.
(bmalloc::Heap::allocateSmallBumpRangesByMetadata): Split out some helper
lambdas to make this code clearer.
(bmalloc::Heap::allocateSmallBumpRangesByObject): Added a fast scan
for objects larger than the line size. When multiple objects fit in
a single line, it's an optimization to scan a line at a time. But when
it's one object per line, or one object per 64 lines, it's better just
to scan an object at a time.
* bmalloc/Heap.h:
(bmalloc::Heap::allocateSmallBumpRanges):
(bmalloc::Heap::derefSmallLine): Match the changes above.
* bmalloc/LineMetadata.h: We weren't using all those bits.
* bmalloc/List.h:
(bmalloc::List::remove): Put a removed Node fully back into the default
(empty) state it was in before it entered the list. This change is not
observable, but it makes things clearer when you're debugging.
* bmalloc/Object.h:
(bmalloc::Object::Object):
(bmalloc::Object::chunk):
(bmalloc::Object::offset):
(bmalloc::Object::operator+):
(bmalloc::Object::operator<=): Added some helpers for iterating by object.
* bmalloc/ObjectType.cpp:
(bmalloc::objectType): Updated for API change.
* bmalloc/Sizes.h:
(bmalloc::Sizes::maskObjectSize):
(bmalloc::Sizes::objectSize):
(bmalloc::Sizes::pageSize): Support more page sizes.
* bmalloc/SmallPage.h:
(bmalloc::SmallPage::SmallPage):
(bmalloc::SmallPage::objectType): Deleted.
(bmalloc::SmallPage::setObjectType): Deleted.
(bmalloc::SmallPage::smallPageCount): Deleted.
(bmalloc::SmallPage::setSmallPageCount): Deleted. Object type is per
Chunk now, and we can infer page count from size class.
* bmalloc/VMHeap.cpp:
(bmalloc::VMHeap::allocateChunk):
(bmalloc::VMHeap::allocateSmallChunk):
* bmalloc/VMHeap.h:
(bmalloc::VMHeap::allocateSmallPage):
(bmalloc::VMHeap::deallocateSmallPage):
(bmalloc::VMHeap::allocateLargeObject): Support our old behavior of
storing free pages in linked lists.
Canonical link: https://commits.webkit.org/174274@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@198995 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-04-04 05:26:43 +00:00
|
|
|
|
2016-02-20 01:06:49 +00:00
|
|
|
private:
|
|
|
|
unsigned char m_hasFreeLines: 1;
|
bmalloc: Small and large objects should share memory
https://bugs.webkit.org/show_bug.cgi?id=172880
<rdar://problem/31494732>
Reviewed by Sam Weinig.
This reduces our high water mark memory usage on JetStream on macOS
by 10%-20%. It also has the nice side effect that we can free small
object metadata after returning from a high water mark.
No change in throughput.
Our old algorithm allocated small object chunks and large objects in
segregated virtual memory and never recycled addresses between them.
This provided a slight security benefit because we could apply guard
pages between the segregated ranges and we would never reuse the same
virtual address for object and metadata memory.
Our new algorithm allocates small object chunks from the large object
allocator. This naturally recycles memory between small chunks and large
objects, and between small chunks of different page classes. This allows
us to shift memory between allocation types as a program moves between
different phases of allocation, and to delete small object chunk metadata
when a program shrinks back from a high water mark.
Two intuitions I had about memory use turned out to be backwards in
this context:
(1) I thought that this optimization would work because it allowed you to
allocate and free a 4MB object and then reuse that large allocation to
service small allocations. In practice, the common benefit seems to be
the opposite: After you allocate and free many small objects, you can
stitch them together to allocate a large object without growing the heap.
(2) I thought that it would be more memory-efficient to allocate
fine-grained pages from the large object allocator. In practice, giving
the large object allocator too many arbitrarily-sized ranges to manage
leads to fragmentation. Meanwhile, segregated fit is a powerful memory
optimization. So, it's best to return small object memory to the large
allocator only when a whole small object chunk is free.
* bmalloc/Chunk.h:
(bmalloc::Chunk::ref):
(bmalloc::Chunk::deref):
(bmalloc::Chunk::refCount):
(bmalloc::Chunk::freePages): We keep a free list per chunk and refcount
each chunk so we can notice when a chunk becomes empty, and return it
to the large allocator.
(bmalloc::forEachPage): A new helper function for iterating the pages
in a Chunk.
(bmalloc::Chunk::Chunk): Use forEachPage instead of manual iteration.
Use { } initialization because we don't get zero-initialized by the OS
anymore.
* bmalloc/Heap.cpp:
(bmalloc::Heap::Heap):
(bmalloc::Heap::concurrentScavenge):
(bmalloc::Heap::scavenge): Don't bother unlocking while scavenging. I
wasn't able to show it to be a consistent speedup. A more promising
approach, if we find a motivating example, is for the scavenger to give
up and return early if any other client is waiting on the lock.
(bmalloc::Heap::allocateSmallChunk): New helper function for allocating
a small chunk. It allocates through the large allocator to facilitate
sharing. We still allocate a chunk at a time instead of a page at a time.
Surprisingly, more precise page-at-a-time allocation is worse for memory
use because of fragmentation. Segregated fit is a powerful optimization.
(bmalloc::Heap::deallocateSmallChunk): New helper function for deallocating
a small chunk.
(bmalloc::Heap::allocateSmallPage): Updated for new APIs.
(bmalloc::Heap::deallocateSmallLine): Updated for new APIs. Note that
we cache one free chunk per page class. This avoids churn in the large
allocator when you free(malloc(X)).
(bmalloc::Heap::allocateSmallBumpRangesByMetadata):
(bmalloc::Heap::allocateSmallBumpRangesByObject):
(bmalloc::Heap::tryAllocateLarge):
(bmalloc::Heap::scavengeSmallPages): Deleted.
(bmalloc::Heap::scavengeLargeObjects): Deleted.
* bmalloc/Heap.h:
* bmalloc/LargeMap.h:
(bmalloc::LargeMap::begin):
(bmalloc::LargeMap::end): Added iteration helpers for scavenging.
* bmalloc/LargeRange.h:
(bmalloc::LargeRange::physicalSize): Added a comment about something
that I confused myself about in this patch.
* bmalloc/List.h:
(bmalloc::List::iterator::operator*):
(bmalloc::List::iterator::operator->):
(bmalloc::List::iterator::operator!=):
(bmalloc::List::iterator::operator++):
(bmalloc::List::begin):
(bmalloc::List::end):
(bmalloc::List::pushFront):
(bmalloc::List::remove):
(bmalloc::ListNode::ListNode): Deleted. Added iteration helpers for
scavenging. Changed the default state of a Node to null pointers instead
of self pointers to distinguish the null node from the empty node for
easier debugging.
* bmalloc/Sizes.h: Changed the chunk size to 1MB to increase the chances
of a chunk becoming free and recyclable.
* bmalloc/SmallPage.h:
(bmalloc::SmallPage::hasPhysicalPages):
(bmalloc::SmallPage::setHasPhysicalPages): Track physical state by page
instead of implicitly by which list a page is in. It's simpler not
to have to move chunks and pages between physical vs virtual lists.
(bmalloc::SmallPage::SmallPage): Deleted.
* bmalloc/VMHeap.cpp:
(bmalloc::VMHeap::tryAllocateLargeChunk):
(bmalloc::VMHeap::allocateSmallChunk): Deleted.
* bmalloc/VMHeap.h:
(bmalloc::VMHeap::allocateSmallPage): Deleted.
(bmalloc::VMHeap::deallocateSmallPage): Deleted. Small chunk allocation
just forwards to the large allocator now.
* bmalloc/bmalloc.h:
(bmalloc::api::scavenge):
Canonical link: https://commits.webkit.org/189836@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@217811 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-06-06 02:21:11 +00:00
|
|
|
unsigned char m_hasPhysicalPages: 1;
|
[BMalloc] Scavenger should react to recent memory activity
https://bugs.webkit.org/show_bug.cgi?id=195895
Reviewed by Geoffrey Garen.
This change adds a recently used bit to objects that are scavenged. When an object is allocated, that bit is set.
When we scavenge, if the bit is set, we clear it. If the bit was already clear, we decommit the object. The timing
to scavenging has been changed as well. We perform our first scavne almost immediately after bmalloc is initialized
(10ms later). Subsequent scavenging is done as a multiple of the time it took to scavenge. We bound this computed
time between a minimum and maximum. Through empirical testing, the multiplier, minimum and maximum are
150x, 100ms and 10,000ms respectively. For mini-mode, when the JIT is disabled, we use much more aggressive values of
50x, 25ms and 500ms.
Eliminated partial scavenging since this change allows for any scavenge to be partial or full based on recent use of
the objects on the various free lists.
* bmalloc/Chunk.h:
(bmalloc::Chunk::usedSinceLastScavenge):
(bmalloc::Chunk::clearUsedSinceLastScavenge):
(bmalloc::Chunk::setUsedSinceLastScavenge):
* bmalloc/Heap.cpp:
(bmalloc::Heap::scavenge):
(bmalloc::Heap::allocateSmallChunk):
(bmalloc::Heap::allocateSmallPage):
(bmalloc::Heap::splitAndAllocate):
(bmalloc::Heap::tryAllocateLarge):
(bmalloc::Heap::scavengeToHighWatermark): Deleted.
* bmalloc/Heap.h:
* bmalloc/IsoDirectory.h:
* bmalloc/IsoDirectoryInlines.h:
(bmalloc::passedNumPages>::takeFirstEligible):
(bmalloc::passedNumPages>::scavenge):
(bmalloc::passedNumPages>::scavengeToHighWatermark): Deleted.
* bmalloc/IsoHeapImpl.h:
* bmalloc/IsoHeapImplInlines.h:
(bmalloc::IsoHeapImpl<Config>::scavengeToHighWatermark): Deleted.
* bmalloc/LargeRange.h:
(bmalloc::LargeRange::LargeRange):
(bmalloc::LargeRange::usedSinceLastScavenge):
(bmalloc::LargeRange::clearUsedSinceLastScavenge):
(bmalloc::LargeRange::setUsedSinceLastScavenge):
(): Deleted.
* bmalloc/Scavenger.cpp:
(bmalloc::Scavenger::Scavenger):
(bmalloc::Scavenger::threadRunLoop):
(bmalloc::Scavenger::timeSinceLastPartialScavenge): Deleted.
(bmalloc::Scavenger::partialScavenge): Deleted.
* bmalloc/Scavenger.h:
* bmalloc/SmallPage.h:
(bmalloc::SmallPage::usedSinceLastScavenge):
(bmalloc::SmallPage::clearUsedSinceLastScavenge):
(bmalloc::SmallPage::setUsedSinceLastScavenge):
Canonical link: https://commits.webkit.org/210213@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@243144 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-03-19 17:31:01 +00:00
|
|
|
unsigned char m_usedSinceLastScavenge: 1;
|
2016-02-20 01:06:49 +00:00
|
|
|
unsigned char m_refCount: 7;
|
|
|
|
unsigned char m_sizeClass;
|
2016-03-30 02:22:47 +00:00
|
|
|
unsigned char m_slide;
|
2016-03-23 01:39:36 +00:00
|
|
|
|
|
|
|
static_assert(
|
|
|
|
sizeClassCount <= std::numeric_limits<decltype(m_sizeClass)>::max(),
|
|
|
|
"Largest size class must fit in SmallPage metadata");
|
2016-02-20 01:06:49 +00:00
|
|
|
};
|
|
|
|
|
2017-06-24 20:14:33 +00:00
|
|
|
using LineCache = std::array<List<SmallPage>, sizeClassCount>;
|
|
|
|
|
2020-01-18 00:43:00 +00:00
|
|
|
inline void SmallPage::ref(UniqueLockHolder&)
|
2016-02-20 01:06:49 +00:00
|
|
|
{
|
2016-03-30 02:22:47 +00:00
|
|
|
BASSERT(!m_slide);
|
2016-02-20 01:06:49 +00:00
|
|
|
++m_refCount;
|
2016-03-23 01:39:36 +00:00
|
|
|
BASSERT(m_refCount);
|
2016-02-20 01:06:49 +00:00
|
|
|
}
|
|
|
|
|
2020-01-18 00:43:00 +00:00
|
|
|
inline bool SmallPage::deref(UniqueLockHolder&)
|
2016-02-20 01:06:49 +00:00
|
|
|
{
|
2016-03-30 02:22:47 +00:00
|
|
|
BASSERT(!m_slide);
|
2016-02-20 01:06:49 +00:00
|
|
|
BASSERT(m_refCount);
|
|
|
|
--m_refCount;
|
|
|
|
return !m_refCount;
|
|
|
|
}
|
2014-04-07 23:54:11 +00:00
|
|
|
|
|
|
|
} // namespace bmalloc
|
|
|
|
|
2016-03-15 05:39:35 +00:00
|
|
|
#endif // SmallPage_h
|