aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/memory/qv4mm.cpp
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2017-05-16 12:42:42 +0200
committerLars Knoll <lars.knoll@qt.io>2017-05-19 06:22:57 +0000
commit2affe19182b99d8d1c9655fa0c58c8af3e0b9506 (patch)
tree1b5b05041bcd4a736a886a5e896e4f1d297c5401 /src/qml/memory/qv4mm.cpp
parent947310e01355b3657bf5d0103545586bf5a9b37c (diff)
Free up completely empty Chunks, and return the memory to the OS
Detect any Chunk that's completely empty, deallocate it and return the memory to the OS (as far as that's supported). Change-Id: I6b6a77f2cdf478cbf16aad30a9cae37c98c6500e Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/memory/qv4mm.cpp')
-rw-r--r--src/qml/memory/qv4mm.cpp30
1 files changed, 22 insertions, 8 deletions
diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp
index 0a6dfb9170..ef36e62373 100644
--- a/src/qml/memory/qv4mm.cpp
+++ b/src/qml/memory/qv4mm.cpp
@@ -275,8 +275,9 @@ QString binary(quintptr) { return QString(); }
#define SDUMP if (1) ; else qDebug
#endif
-void Chunk::sweep()
+bool Chunk::sweep()
{
+ bool hasUsedSlots = false;
SDUMP() << "sweeping chunk" << this;
HeapItem *o = realBase();
bool lastSlotFree = false;
@@ -316,6 +317,7 @@ void Chunk::sweep()
}
}
objectBitmap[i] = blackBitmap[i];
+ hasUsedSlots |= (blackBitmap[i] != 0);
blackBitmap[i] = 0;
extendsBitmap[i] = e;
lastSlotFree = !((objectBitmap[i]|extendsBitmap[i]) >> (sizeof(quintptr)*8 - 1));
@@ -325,6 +327,7 @@ void Chunk::sweep()
o += Chunk::Bits;
}
// DEBUG << "swept chunk" << this << "freed" << slotsFreed << "slots.";
+ return hasUsedSlots;
}
void Chunk::freeAll()
@@ -579,12 +582,21 @@ void BlockAllocator::sweep()
// qDebug() << "BlockAlloc: sweep";
usedSlotsAfterLastSweep = 0;
- for (auto c : chunks) {
- c->sweep();
- c->sortIntoBins(freeBins, NumBins);
-// qDebug() << "used slots in chunk" << c << ":" << c->nUsedSlots();
- usedSlotsAfterLastSweep += c->nUsedSlots();
- }
+
+ auto isFree = [this] (Chunk *c) {
+ bool isUsed = c->sweep();
+
+ if (isUsed) {
+ c->sortIntoBins(freeBins, NumBins);
+ usedSlotsAfterLastSweep += c->nUsedSlots();
+ } else {
+ chunkAllocator->free(c);
+ }
+ return !isUsed;
+ };
+
+ auto newEnd = std::remove_if(chunks.begin(), chunks.end(), isFree);
+ chunks.erase(newEnd, chunks.end());
}
void BlockAllocator::freeAll()
@@ -950,7 +962,8 @@ void MemoryManager::runGC()
#ifndef QT_NO_DEBUG
qDebug() << " Triggered by alloc request of" << lastAllocRequestedSlots << "slots.";
#endif
- qDebug() << "Allocated" << totalMem << "bytes in" << blockAllocator.chunks.size() << "chunks";
+ size_t oldChunks = blockAllocator.chunks.size();
+ qDebug() << "Allocated" << totalMem << "bytes in" << oldChunks << "chunks";
qDebug() << "Fragmented memory before GC" << (totalMem - usedBefore);
dumpBins(&blockAllocator);
@@ -975,6 +988,7 @@ void MemoryManager::runGC()
qDebug() << "Used memory before GC:" << usedBefore;
qDebug() << "Used memory after GC:" << usedAfter;
qDebug() << "Freed up bytes:" << (usedBefore - usedAfter);
+ qDebug() << "Freed up chunks:" << (oldChunks - blockAllocator.chunks.size());
size_t lost = blockAllocator.allocatedMem() - memInBins - usedAfter;
if (lost)
qDebug() << "!!!!!!!!!!!!!!!!!!!!! LOST MEM:" << lost << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!";