1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-12 05:14:10 +02:00

GC marking in addr order for cache, improved reporting

This commit is contained in:
Brian Fiete 2019-11-07 10:01:23 -08:00
parent 9197c60964
commit 9c9bfdc6d4
4 changed files with 216 additions and 52 deletions

View file

@ -42,6 +42,7 @@
#include "BeefySysLib/util/BeefPerf.h" #include "BeefySysLib/util/BeefPerf.h"
#include "BeefySysLib/util/HashSet.h" #include "BeefySysLib/util/HashSet.h"
#include "BeefySysLib/util/Dictionary.h" #include "BeefySysLib/util/Dictionary.h"
#include "BeefySysLib/util/BinaryHeap.h"
#include <unordered_set> #include <unordered_set>
#include "../rt/BfObjects.h" #include "../rt/BfObjects.h"
#include "../rt/Thread.h" #include "../rt/Thread.h"
@ -586,8 +587,8 @@ BFGC::BFGC()
mGracelessShutdown = false; mGracelessShutdown = false;
mMainThreadTLSPtr = NULL; mMainThreadTLSPtr = NULL;
mHadPendingGCDataOverflow = false; mHadPendingGCDataOverflow = false;
mCurPendingGCDepth = 0; mCurPendingGCSize = 0;
mMaxPendingGCDepth = 0; mMaxPendingGCSize = 0;
mCollectIdx = 0; mCollectIdx = 0;
mStackScanIdx = 0; mStackScanIdx = 0;
@ -851,33 +852,28 @@ void BFGC::ObjectDeleteRequested(bf::System::Object* obj)
} }
} }
bool BFGC::HandlePendingGCData(Beefy::Array<bf::System::Object*>* pendingGCData) bool BFGC::HandlePendingGCData()
{ {
int count = 0; int count = 0;
while (!pendingGCData->IsEmpty()) while (true)
{ {
mCurPendingGCDepth = 0; if (mOrderedPendingGCData.IsEmpty())
break;
mCurPendingGCSize = 0;
bf::System::Object* obj = pendingGCData->back(); bf::System::Object* obj = mOrderedPendingGCData.Pop();
pendingGCData->pop_back();
MarkMembers(obj); MarkMembers(obj);
count++; count++;
if (mCurPendingGCDepth > mMaxPendingGCDepth) if (mCurPendingGCSize > mMaxPendingGCSize)
mMaxPendingGCDepth = mCurPendingGCDepth; mMaxPendingGCSize = mCurPendingGCSize;
} }
return count > 0; return count > 0;
} }
bool BFGC::HandlePendingGCData()
{
bool didMark = false;
didMark = HandlePendingGCData(&mPendingGCData);
return didMark;
}
void BFGC::SweepSpan(tcmalloc_obj::Span* span, int expectedStartPage) void BFGC::SweepSpan(tcmalloc_obj::Span* span, int expectedStartPage)
{ {
if ((gBfRtDbgFlags & BfRtFlags_ObjectHasDebugFlags) == 0) if ((gBfRtDbgFlags & BfRtFlags_ObjectHasDebugFlags) == 0)
@ -1446,7 +1442,7 @@ bool BFGC::ScanThreads()
//suspendTimeGuard.Stop(); //suspendTimeGuard.Stop();
BF_LOGASSERT(result != -1); BF_LOGASSERT(result != -1);
if (!mPendingGCData.IsEmpty()) if ((!mOrderedPendingGCData.IsEmpty()) || (!mOrderedPendingGCData.IsEmpty()))
{ {
BP_ZONE("HandlePendingGCData(Thread)"); BP_ZONE("HandlePendingGCData(Thread)");
HandlePendingGCData(); HandlePendingGCData();
@ -1608,7 +1604,7 @@ void BFGC::DoCollect(bool doingFullGC)
} }
} }
BF_ASSERT(mPendingGCData.IsEmpty()); BF_ASSERT(mOrderedPendingGCData.IsEmpty());
} }
void BFGC::FinishCollect() void BFGC::FinishCollect()
@ -1825,11 +1821,11 @@ void BFGC::Run()
while (true) while (true)
{ {
mHadPendingGCDataOverflow = false; mHadPendingGCDataOverflow = false;
mMaxPendingGCDepth = 0; mMaxPendingGCSize = 0;
PerformCollection(); PerformCollection();
if (!mHadPendingGCDataOverflow) if (!mHadPendingGCDataOverflow)
break; break;
mPendingGCData.Reserve(BF_MAX(mPendingGCData.mAllocSize + mPendingGCData.mAllocSize / 2, mMaxPendingGCDepth + 256)); mOrderedPendingGCData.Reserve(BF_MAX(mOrderedPendingGCData.mAllocSize + mOrderedPendingGCData.mAllocSize / 2, mMaxPendingGCSize + 256));
} }
BF_FULL_MEMORY_FENCE(); BF_FULL_MEMORY_FENCE();
@ -1997,7 +1993,7 @@ void BFGC::Shutdown()
TCMalloc_FreeAllocs(); TCMalloc_FreeAllocs();
mFinalizeList.Dispose(); mFinalizeList.Dispose();
mPendingGCData.Dispose(); mOrderedPendingGCData.Dispose();
for (auto thread : mThreadList) for (auto thread : mThreadList)
thread->mStackMarkableObjects.Dispose(); thread->mStackMarkableObjects.Dispose();
} }
@ -2070,8 +2066,8 @@ void BFGC::ObjReportHandleSpan(tcmalloc_obj::Span* span, int expectedStartPage,
//pairVal.first->second = newSize; //pairVal.first->second = newSize;
AllocInfo* sizePtr = NULL; AllocInfo* sizePtr = NULL;
sizeMap.TryAdd(type, NULL, &sizePtr); sizeMap.TryAdd(type, NULL, &sizePtr);
sizePtr->mCount++; sizePtr->mObjCount++;
sizePtr->mSize += elementSize; sizePtr->mObjSize += elementSize;
objectCount++; objectCount++;
} }
@ -2167,8 +2163,7 @@ void BFGC::Report()
ObjReportScan(objectCount, objFreeSize, sizeMap); ObjReportScan(objectCount, objFreeSize, sizeMap);
std::multimap<AllocInfo, bf::System::Type*> orderedSizeMap; std::multimap<AllocInfo, bf::System::Type*> orderedSizeMap;
intptr totalSize = 0;
for (auto& pair : sizeMap) for (auto& pair : sizeMap)
{ {
orderedSizeMap.insert(std::make_pair(pair.mValue, pair.mKey)); orderedSizeMap.insert(std::make_pair(pair.mValue, pair.mKey));
@ -2182,18 +2177,25 @@ void BFGC::Report()
msg += Beefy::StrFormat(" Live Objects %d\n", objectCount); msg += Beefy::StrFormat(" Live Objects %d\n", objectCount);
msg += Beefy::StrFormat(" Last Object Freed Count %d\n", mLastFreeCount); msg += Beefy::StrFormat(" Last Object Freed Count %d\n", mLastFreeCount);
intptr reportedCount = 0; intptr objReportedCount = 0;
intptr rawFreeSize = 0; intptr rawReportedCount = 0;
intptr rawFreeSize = 0;
intptr objTotalSize = 0;
intptr rawTotalSize = 0;
gBFGC.RawReport(msg, rawFreeSize, orderedSizeMap); gBFGC.RawReport(msg, rawFreeSize, orderedSizeMap);
for (auto& pair : orderedSizeMap) for (auto& pair : orderedSizeMap)
{ {
totalSize += pair.first.mSize; objTotalSize += pair.first.mObjSize;
reportedCount += pair.first.mCount; objReportedCount += pair.first.mObjCount;
rawTotalSize += pair.first.mRawSize;
rawReportedCount += pair.first.mRawCount;
} }
msg += Beefy::StrFormat(" Scanned Alloc Count %d\n", (int)(reportedCount)); msg += Beefy::StrFormat(" Obj Scanned Alloc Count %d\n", (int)(objReportedCount));
msg += Beefy::StrFormat(" Used Memory %dk\n", (int)(totalSize / 1024)); msg += Beefy::StrFormat(" Raw Scanned Alloc Count %d\n", (int)(rawReportedCount));
msg += Beefy::StrFormat(" Object Unusued Memory %dk\n", (int)(objFreeSize / 1024)); msg += Beefy::StrFormat(" Obj Used Memory %dk\n", (int)(objTotalSize / 1024));
msg += Beefy::StrFormat(" Raw Used Memory %dk\n", (int)(rawTotalSize / 1024));
msg += Beefy::StrFormat(" Obj Unusued Memory %dk\n", (int)(objFreeSize / 1024));
msg += Beefy::StrFormat(" Raw Unusued Memory %dk\n", (int)(rawFreeSize / 1024)); msg += Beefy::StrFormat(" Raw Unusued Memory %dk\n", (int)(rawFreeSize / 1024));
@ -2216,7 +2218,7 @@ void BFGC::Report()
msg += Beefy::StrFormat(" Average Time Between Collections %dms\n", BFTickCount() / mCollectIdx); msg += Beefy::StrFormat(" Average Time Between Collections %dms\n", BFTickCount() / mCollectIdx);
} }
msg += "Types Size Count\n"; msg += "Types Size Count\n";
for (auto& pair : orderedSizeMap) for (auto& pair : orderedSizeMap)
{ {
bf::System::Type* type = pair.second; bf::System::Type* type = pair.second;
@ -2225,8 +2227,11 @@ void BFGC::Report()
typeName = "NULL"; typeName = "NULL";
else else
typeName = type->GetFullName(); typeName = type->GetFullName();
msg += StrFormat(" %-62s %7dk %7d\n", typeName.c_str(), (pair.first.mSize + 1023) / 1024, pair.first.mCount); if (pair.first.mObjCount > 0)
msg += StrFormat("OBJ %-62s %7dk %7d\n", typeName.c_str(), (pair.first.mObjSize + 1023) / 1024, pair.first.mObjCount);
if (pair.first.mRawCount > 0)
msg += StrFormat("RAW %-62s %7dk %7d\n", typeName.c_str(), (pair.first.mRawSize + 1023) / 1024, pair.first.mRawCount);
} }
Beefy::OutputDebugStr(msg.c_str()); Beefy::OutputDebugStr(msg.c_str());
@ -2313,7 +2318,7 @@ void BFGC::PerformCollection()
uint8 oldCode = *mallocAddr; uint8 oldCode = *mallocAddr;
*mallocAddr = 0xCC;*/ *mallocAddr = 0xCC;*/
mPendingGCData.Reserve(BF_GC_MAX_PENDING_OBJECT_COUNT); mOrderedPendingGCData.Reserve(BF_GC_MAX_PENDING_OBJECT_COUNT);
uint32 suspendStartTick = BFTickCount(); uint32 suspendStartTick = BFTickCount();
SuspendThreads(); SuspendThreads();
@ -2579,13 +2584,14 @@ void BFGC::MarkFromGCThread(bf::System::Object* obj)
mCurGCMarkCount++; mCurGCMarkCount++;
mCurGCObjectQueuedCount++; mCurGCObjectQueuedCount++;
mCurPendingGCDepth++; mCurPendingGCSize++;
bool allowQueue = true; bool allowQueue = true;
if (mPendingGCData.GetFreeCount() > 0)
if (mOrderedPendingGCData.GetFreeCount() > 0)
{ {
mPendingGCData.Add(obj); mOrderedPendingGCData.Add(obj);
} }
else else
{ {
mHadPendingGCDataOverflow = true; mHadPendingGCDataOverflow = true;

View file

@ -4,6 +4,7 @@
#include "BeefySysLib/util/CritSect.h" #include "BeefySysLib/util/CritSect.h"
#include "BeefySysLib/util/Array.h" #include "BeefySysLib/util/Array.h"
#include "BeefySysLib/util/Dictionary.h" #include "BeefySysLib/util/Dictionary.h"
#include "BeefySysLib/util/BinaryHeap.h"
#include <unordered_map> #include <unordered_map>
#include <map> #include <map>
#include "../rt/BfObjects.h" #include "../rt/BfObjects.h"
@ -238,12 +239,15 @@ public:
struct AllocInfo struct AllocInfo
{ {
int mCount; int mObjCount;
int mSize; int mObjSize;
int mRawCount;
int mRawSize;
bool operator<(const AllocInfo &rhs) const bool operator<(const AllocInfo &rhs) const
{ {
return mSize > rhs.mSize; return (mObjSize + mRawSize) > (rhs.mObjSize + rhs.mRawSize);
} }
}; };
@ -301,10 +305,11 @@ public:
static int volatile sCurMarkId; //0-3 static int volatile sCurMarkId; //0-3
static int volatile sAllocFlags; static int volatile sAllocFlags;
Beefy::Array<bf::System::Object*> mPendingGCData; Beefy::BinaryMinHeap<bf::System::Object*> mOrderedPendingGCData;
bool mHadPendingGCDataOverflow;
int mCurPendingGCDepth; bool mHadPendingGCDataOverflow;
int mMaxPendingGCDepth; int mCurPendingGCSize;
int mMaxPendingGCSize;
Beefy::Array<ThreadInfo*> mThreadList; Beefy::Array<ThreadInfo*> mThreadList;
int mCurMutatorMarkCount; int mCurMutatorMarkCount;
int mCurGCMarkCount; int mCurGCMarkCount;
@ -335,8 +340,7 @@ public:
public: public:
void RawInit(); void RawInit();
void RawShutdown(); void RawShutdown();
void WriteDebugDumpState(); void WriteDebugDumpState();
bool HandlePendingGCData(Beefy::Array<bf::System::Object*>* pendingGCData);
bool HandlePendingGCData(); bool HandlePendingGCData();
void MarkMembers(bf::System::Object* obj); void MarkMembers(bf::System::Object* obj);

View file

@ -292,8 +292,8 @@ void BFGC::RawReportHandleSpan(tcmalloc_raw::Span* span, int expectedStartPage,
else else
{ {
(*sizeMap).TryAdd(type, NULL, &sizePtr); (*sizeMap).TryAdd(type, NULL, &sizePtr);
sizePtr->mSize += elementSize; sizePtr->mRawSize += elementSize;
sizePtr->mCount++; sizePtr->mRawCount++;
} }
objectCount++; objectCount++;
} }

View file

@ -0,0 +1,154 @@
#pragma once
#include "Array.h"
NS_BF_BEGIN;
template <typename T>
class BinaryMaxHeap : public Array<T>
{
private:
void HeapifyUp(int32 childIdx)
{
if (childIdx > 0)
{
int32 parentIdx = (childIdx - 1) / 2;
if (mVals[childIdx] > mVals[parentIdx])
{
// swap parent and child
T t = mVals[parentIdx];
mVals[parentIdx] = mVals[childIdx];
mVals[childIdx] = t;
HeapifyUp(parentIdx);
}
}
}
void HeapifyDown(int32 parentIdx)
{
int32 leftChildIdx = 2 * parentIdx + 1;
int32 rightChildIdx = leftChildIdx + 1;
int32 largestChildIdx = parentIdx;
if (leftChildIdx < mSize && mVals[leftChildIdx] > mVals[largestChildIdx])
{
largestChildIdx = leftChildIdx;
}
if (rightChildIdx < mSize && mVals[rightChildIdx] > mVals[largestChildIdx])
{
largestChildIdx = rightChildIdx;
}
if (largestChildIdx != parentIdx)
{
T t = mVals[parentIdx];
mVals[parentIdx] = mVals[largestChildIdx];
mVals[largestChildIdx] = t;
HeapifyDown(largestChildIdx);
}
}
public:
BinaryMaxHeap() : Array()
{
}
/// Add an item to the heap
void Add(T item)
{
Array::Add(item);
HeapifyUp(mSize - 1);
}
/// Get the item of the root
T Peek()
{
return mVals[0];
}
/// Extract the item of the root
T Pop()
{
T item = mVals[0];
mSize--;
mVals[0] = mVals[mSize];
HeapifyDown(0);
return item;
}
};
template <typename T>
class BinaryMinHeap : public Array<T>
{
private:
void HeapifyUp(int32 childIdx)
{
if (childIdx > 0)
{
int32 parentIdx = (childIdx - 1) / 2;
if (mVals[childIdx] < mVals[parentIdx])
{
// swap parent and child
T t = mVals[parentIdx];
mVals[parentIdx] = mVals[childIdx];
mVals[childIdx] = t;
HeapifyUp(parentIdx);
}
}
}
void HeapifyDown(int32 parentIdx)
{
int32 leftChildIdx = 2 * parentIdx + 1;
int32 rightChildIdx = leftChildIdx + 1;
int32 largestChildIdx = parentIdx;
if (leftChildIdx < mSize && mVals[leftChildIdx] < mVals[largestChildIdx])
{
largestChildIdx = leftChildIdx;
}
if (rightChildIdx < mSize && mVals[rightChildIdx] < mVals[largestChildIdx])
{
largestChildIdx = rightChildIdx;
}
if (largestChildIdx != parentIdx)
{
T t = mVals[parentIdx];
mVals[parentIdx] = mVals[largestChildIdx];
mVals[largestChildIdx] = t;
HeapifyDown(largestChildIdx);
}
}
public:
BinaryMinHeap() : Array()
{
}
/// Add an item to the heap
void Add(T item)
{
Array::Add(item);
HeapifyUp(mSize - 1);
}
/// Get the item of the root
T Peek()
{
return mVals[0];
}
/// Extract the item of the root
T Pop()
{
T item = mVals[0];
mSize--;
mVals[0] = mVals[mSize];
HeapifyDown(0);
return item;
}
};
NS_BF_END