Add shared gc trigger

Description:Add shared gc trigger
Issue:https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I9D0AG?from=project-issue

Signed-off-by: dingwen <dingwen6@huawei.com>
Change-Id: I0bb112de15f32d555b3a5bdd6432d834c20b17ce
This commit is contained in:
dingwen 2024-03-31 16:24:12 +08:00
parent 89ae8776aa
commit c5d23e3eec
10 changed files with 102 additions and 19 deletions

View File

@ -67,6 +67,7 @@ public:
defaultNonMovableSpaceSize_ = 2_MB;
defaultSnapshotSpaceSize_ = 512_KB;
defaultMachineCodeSpaceSize_ = 2_MB;
defaultGlobalAllocLimit_ = 20_MB;
semiSpaceTriggerConcurrentMark_ = 1_MB;
semiSpaceStepOvershootSize_ = 2_MB;
oldSpaceOvershootSize_ = 4_MB;
@ -75,6 +76,8 @@ public:
minGrowingStep_ = 4_MB;
maxStackSize_ = 128_KB;
maxJSSerializerSize_ = 8_MB;
sharedHeapLimitGrowingFactor_ = 2; // 2: growing factor
sharedHeapLimitGrowingStep_ = 20_MB;
} else if (maxHeapSize_ < HIGH_MEMORY) { // 128_MB ~ 256_MB
minSemiSpaceSize_ = 2_MB;
maxSemiSpaceSize_ = 8_MB;
@ -82,6 +85,7 @@ public:
defaultNonMovableSpaceSize_ = 6_MB;
defaultSnapshotSpaceSize_ = 512_KB;
defaultMachineCodeSpaceSize_ = 2_MB;
defaultGlobalAllocLimit_ = 20_MB;
semiSpaceTriggerConcurrentMark_ = 1.5_MB;
semiSpaceStepOvershootSize_ = 2_MB;
oldSpaceOvershootSize_ = 8_MB;
@ -90,6 +94,8 @@ public:
minGrowingStep_ = 8_MB;
maxStackSize_ = 128_KB;
maxJSSerializerSize_ = 16_MB;
sharedHeapLimitGrowingFactor_ = 2; // 2: growing factor
sharedHeapLimitGrowingStep_ = 40_MB;
} else { // 256_MB ~ 384_MB
minSemiSpaceSize_ = 2_MB;
maxSemiSpaceSize_ = 16_MB;
@ -97,6 +103,7 @@ public:
defaultNonMovableSpaceSize_ = 64_MB;
defaultSnapshotSpaceSize_ = 4_MB;
defaultMachineCodeSpaceSize_ = 8_MB;
defaultGlobalAllocLimit_ = 20_MB;
semiSpaceTriggerConcurrentMark_ = 1.5_MB;
semiSpaceStepOvershootSize_ = 2_MB;
oldSpaceOvershootSize_ = 8_MB;
@ -105,6 +112,8 @@ public:
minGrowingStep_ = 16_MB;
maxStackSize_ = 128_KB;
maxJSSerializerSize_ = 16_MB;
sharedHeapLimitGrowingFactor_ = 2; // 2: growing factor
sharedHeapLimitGrowingStep_ = 40_MB;
}
}
@ -143,6 +152,11 @@ public:
return defaultMachineCodeSpaceSize_;
}
size_t GetDefaultGlobalAllocLimit() const
{
return defaultGlobalAllocLimit_;
}
size_t GetSemiSpaceTriggerConcurrentMark() const
{
return semiSpaceTriggerConcurrentMark_;
@ -173,6 +187,16 @@ public:
return minGrowingStep_;
}
size_t GetSharedHeapLimitGrowingFactor() const
{
return sharedHeapLimitGrowingFactor_;
}
size_t GetSharedHeapLimitGrowingStep() const
{
return sharedHeapLimitGrowingStep_;
}
uint32_t GetMaxStackSize() const
{
return maxStackSize_;
@ -207,12 +231,15 @@ private:
size_t defaultNonMovableSpaceSize_ {0};
size_t defaultSnapshotSpaceSize_ {0};
size_t defaultMachineCodeSpaceSize_ {0};
size_t defaultGlobalAllocLimit_ {0};
size_t semiSpaceTriggerConcurrentMark_ {0};
size_t semiSpaceStepOvershootSize_ {0};
size_t oldSpaceOvershootSize_ {0};
size_t outOfMemoryOvershootSize_ {0};
size_t minAllocLimitGrowingStep_ {0};
size_t minGrowingStep_ {0};
size_t sharedHeapLimitGrowingFactor_ {0};
size_t sharedHeapLimitGrowingStep_ {0};
size_t maxJSSerializerSize_ {0};
uint32_t maxStackSize_ {0};
};

View File

@ -401,9 +401,9 @@ void JSThread::IterateHandleWithCheck(const RootVisitor &visitor, const RootRang
}
}
void JSThread::IterateWeakEcmaGlobalStorage(const WeakRootVisitor &visitor, bool isSharedGC)
void JSThread::IterateWeakEcmaGlobalStorage(const WeakRootVisitor &visitor, GCKind gcKind)
{
auto callBack = [this, visitor, isSharedGC](WeakNode *node) {
auto callBack = [this, visitor, gcKind](WeakNode *node) {
JSTaggedValue value(node->GetObject());
if (!value.IsHeapObject()) {
return;
@ -422,7 +422,7 @@ void JSThread::IterateWeakEcmaGlobalStorage(const WeakRootVisitor &visitor, bool
if (!freeGlobalCallBack) {
// If no callback, dispose global immediately
DisposeGlobalHandle(ToUintPtr(node));
} else if (isSharedGC) {
} else if (gcKind == GCKind::SHARED_GC) {
// For shared GC, free global should defer execute in its own thread
weakNodeFreeGlobalCallbacks_.push_back(std::make_pair(freeGlobalCallBack, node->GetReference()));
} else {

View File

@ -52,6 +52,11 @@ enum class MarkStatus : uint8_t {
MARK_FINISHED,
};
enum class GCKind : uint8_t {
LOCAL_GC,
SHARED_GC
};
enum class PGOProfilerStatus : uint8_t {
PGO_PROFILER_DISABLE,
PGO_PROFILER_ENABLE,
@ -371,7 +376,7 @@ public:
return os::thread::GetCurrentThreadId();
}
void IterateWeakEcmaGlobalStorage(const WeakRootVisitor &visitor, bool isSharedGC = false);
void IterateWeakEcmaGlobalStorage(const WeakRootVisitor &visitor, GCKind gcKind = GCKind::LOCAL_GC);
PUBLIC_API PropertiesCache *GetPropertiesCache() const;

View File

@ -567,7 +567,7 @@ TaggedObject *SharedHeap::AllocateHugeObject(JSThread *thread, JSHClass *hclass,
TaggedObject *SharedHeap::AllocateHugeObject(JSThread *thread, size_t size)
{
// Check whether it is necessary to trigger Shared GC before expanding to avoid OOM risk.
CheckHugeAndTriggerGC(thread, size);
CheckHugeAndTriggerSharedGC(thread, size);
auto *object = reinterpret_cast<TaggedObject *>(sHugeObjectSpace_->Allocate(thread, size));
if (UNLIKELY(object == nullptr)) {
CollectGarbage(thread, TriggerGCType::SHARED_GC, GCReason::ALLOCATION_LIMIT);

View File

@ -68,7 +68,7 @@ SharedHeap* SharedHeap::GetInstance()
return shareHeap;
}
bool SharedHeap::CheckAndTriggerGC(JSThread *thread)
bool SharedHeap::CheckAndTriggerSharedGC(JSThread *thread)
{
if ((OldSpaceExceedLimit() || GetHeapObjectSize() > globalSpaceAllocLimit_) &&
!NeedStopCollection()) {
@ -78,15 +78,39 @@ bool SharedHeap::CheckAndTriggerGC(JSThread *thread)
return false;
}
bool SharedHeap::CheckHugeAndTriggerGC(JSThread *thread, size_t size)
bool SharedHeap::CheckHugeAndTriggerSharedGC(JSThread *thread, size_t size)
{
if (sHugeObjectSpace_->CommittedSizeExceed(size) && !NeedStopCollection()) {
if ((sHugeObjectSpace_->CommittedSizeExceed(size) || GetHeapObjectSize() > globalSpaceAllocLimit_) &&
!NeedStopCollection()) {
CollectGarbage(thread, TriggerGCType::SHARED_GC, GCReason::ALLOCATION_LIMIT);
return true;
}
return false;
}
// Shared gc trigger
void SharedHeap::AdjustGlobalSpaceAllocLimit()
{
globalSpaceAllocLimit_ = std::max(GetHeapObjectSize() * growingFactor_, config_.GetDefaultGlobalAllocLimit());
globalSpaceAllocLimit_ = std::min(std::min(globalSpaceAllocLimit_, GetCommittedSize() + growingStep_),
config_.GetMaxHeapSize());
LOG_ECMA(INFO) << "Shared gc adjust global space alloc limit to: " << globalSpaceAllocLimit_;
}
bool SharedHeap::ObjectExceedMaxHeapSize() const
{
return OldSpaceExceedLimit() || sHugeObjectSpace_->CommittedSizeExceed();
}
bool SharedHeap::MainThreadInSensitiveStatus() const
{
JSThread *mainThread = Runtime::GetInstance()->GetMainThread();
if (mainThread == nullptr) {
return false;
}
return const_cast<Heap *>(mainThread->GetEcmaVM()->GetHeap())->InSensitiveStatus();
}
void SharedHeap::Initialize(NativeAreaAllocator *nativeAreaAllocator, HeapRegionAllocator *heapRegionAllocator,
const JSRuntimeOptions &option)
{
@ -101,11 +125,13 @@ void SharedHeap::Initialize(NativeAreaAllocator *nativeAreaAllocator, HeapRegion
size_t readOnlySpaceCapacity = config_.GetDefaultReadOnlySpaceSize();
size_t oldSpaceCapacity = (maxHeapSize - nonmovableSpaceCapacity - readOnlySpaceCapacity) / 2; // 2: half
globalSpaceAllocLimit_ = maxHeapSize;
globalSpaceAllocLimit_ = config_.GetDefaultGlobalAllocLimit();
sOldSpace_ = new SharedOldSpace(this, oldSpaceCapacity, oldSpaceCapacity);
sReadOnlySpace_ = new SharedReadOnlySpace(this, readOnlySpaceCapacity, readOnlySpaceCapacity);
sHugeObjectSpace_ = new SharedHugeObjectSpace(this, heapRegionAllocator_, oldSpaceCapacity, oldSpaceCapacity);
growingFactor_ = config_.GetSharedHeapLimitGrowingFactor();
growingStep_ = config_.GetSharedHeapLimitGrowingStep();
}
void SharedHeap::PostInitialization(const GlobalEnvConstants *globalEnvConstants, const JSRuntimeOptions &option)
@ -167,6 +193,8 @@ void SharedHeap::CollectGarbageImpl(TriggerGCType gcType, GCReason reason)
sharedGC_->RunPhases();
// Record alive object size after shared gc
NotifyHeapAliveSizeAfterGC(GetHeapObjectSize());
// Adjust shared gc trigger threshold
AdjustGlobalSpaceAllocLimit();
if (UNLIKELY(ShouldVerifyHeap())) {
// pre gc heap verify
LOG_ECMA(DEBUG) << "after gc shared heap verify";
@ -279,6 +307,18 @@ size_t SharedHeap::VerifyHeapObjects(VerifyKind verifyKind) const
return failCount;
}
bool SharedHeap::NeedStopCollection()
{
if (!MainThreadInSensitiveStatus()) {
return false;
}
if (!ObjectExceedMaxHeapSize()) {
return true;
}
return false;
}
Heap::Heap(EcmaVM *ecmaVm)
: BaseHeap(ecmaVm->GetEcmaParamConfiguration()),
ecmaVm_(ecmaVm), thread_(ecmaVm->GetJSThread()) {}

View File

@ -132,6 +132,8 @@ public:
virtual GCStats *GetEcmaGCStats() = 0;
virtual bool ObjectExceedMaxHeapSize() const = 0;
void SetMarkType(MarkType markType)
{
markType_ = markType;
@ -327,6 +329,7 @@ public:
void EnableParallelGC(JSRuntimeOptions &option);
void DisableParallelGC();
void AdjustGlobalSpaceAllocLimit();
class ParallelMarkTask : public Task {
public:
ParallelMarkTask(int32_t id, SharedHeap *heap)
@ -364,14 +367,13 @@ public:
return true;
}
bool NeedStopCollection() override
{
return onSerializeEvent_;
}
bool NeedStopCollection() override;
bool CheckAndTriggerGC(JSThread *thread);
bool ObjectExceedMaxHeapSize() const override;
bool CheckHugeAndTriggerGC(JSThread *thread, size_t size);
bool CheckAndTriggerSharedGC(JSThread *thread);
bool CheckHugeAndTriggerSharedGC(JSThread *thread, size_t size);
void TryTriggerLocalConcurrentMarking(JSThread *currentThread);
@ -414,6 +416,8 @@ public:
return parallelGC_;
}
bool MainThreadInSensitiveStatus() const;
SharedOldSpace *GetOldSpace() const
{
return sOldSpace_;
@ -556,6 +560,8 @@ private:
SharedConcurrentSweeper *sSweeper_ {nullptr};
SharedGC *sharedGC_ {nullptr};
SharedGCMarker *sharedGCMarker_ {nullptr};
size_t growingFactor_ {0};
size_t growingStep_ {0};
};
class Heap : public BaseHeap {
@ -904,7 +910,7 @@ public:
void HandleExitHighSensitiveEvent();
bool ObjectExceedMaxHeapSize() const;
bool ObjectExceedMaxHeapSize() const override;
bool NeedStopCollection() override;

View File

@ -88,7 +88,7 @@ void SharedGC::Sweep()
Runtime::GetInstance()->GCIterateThreadList([&](JSThread *thread) {
ASSERT(!thread->IsInRunningState());
thread->GetCurrentEcmaContext()->ProcessNativeDeleteInSharedGC(gcUpdateWeak);
thread->IterateWeakEcmaGlobalStorage(gcUpdateWeak, true);
thread->IterateWeakEcmaGlobalStorage(gcUpdateWeak, GCKind::SHARED_GC);
thread->GetEcmaVM()->ProcessSharedNativeDelete(gcUpdateWeak);
});

View File

@ -75,7 +75,7 @@ uintptr_t SharedSparseSpace::Allocate(JSThread *thread, size_t size, bool allowG
CHECK_SOBJECT_AND_INC_OBJ_SIZE(size);
}
// Check whether it is necessary to trigger Shared GC before expanding to avoid OOM risk.
if (allowGC && sHeap_->CheckAndTriggerGC(thread)) {
if (allowGC && sHeap_->CheckAndTriggerSharedGC(thread)) {
object = TryAllocate(thread, size);
CHECK_SOBJECT_AND_INC_OBJ_SIZE(size);
}

View File

@ -208,7 +208,7 @@ public:
void InvokeAllocationInspector(Address object, size_t objectSize);
bool CommittedSizeExceed(size_t size) const
bool CommittedSizeExceed(size_t size = 0) const
{
return committedSize_ + size >= maximumCapacity_ + outOfMemoryOvershootSize_;
}

View File

@ -46,6 +46,11 @@ public:
void ResumeAll(JSThread *current);
void IterateSerializeRoot(const RootVisitor &v);
JSThread *GetMainThread() const
{
return mainThread_;
}
MutatorLock *GetMutatorLock()
{
return &mutatorLock_;