mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-30 21:51:21 +00:00
!6736 Add shared gc trigger
Merge pull request !6736 from dingwen/shared_gc
This commit is contained in:
commit
eaa9bbd6ea
@ -48,6 +48,7 @@ enum class GCReason : uint8_t {
|
||||
IDLE,
|
||||
SWITCH_BACKGROUND,
|
||||
EXTERNAL_TRIGGER,
|
||||
WORKER_DESTRUCTION,
|
||||
OTHER,
|
||||
};
|
||||
|
||||
|
@ -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_ = 4; // 4: growing factor
|
||||
sharedHeapLimitGrowingStep_ = 80_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};
|
||||
};
|
||||
|
@ -259,7 +259,7 @@ bool EcmaVM::Initialize()
|
||||
auto context = new EcmaContext(thread_);
|
||||
thread_->PushContext(context);
|
||||
[[maybe_unused]] EcmaHandleScope scope(thread_);
|
||||
thread_->SetReadyForGCIterating();
|
||||
thread_->SetReadyForGCIterating(true);
|
||||
snapshotEnv_ = new SnapshotEnv(this);
|
||||
context->Initialize();
|
||||
snapshotEnv_->AddGlobalConstToMap();
|
||||
@ -347,6 +347,14 @@ EcmaVM::~EcmaVM()
|
||||
heap_ = nullptr;
|
||||
}
|
||||
|
||||
SharedHeap *sHeap = SharedHeap::GetInstance();
|
||||
const Heap *heap = Runtime::GetInstance()->GetMainThread()->GetEcmaVM()->GetHeap();
|
||||
if (heap && IsWorkerThread() && Runtime::SharedGCRequest() && !heap->InSensitiveStatus()) {
|
||||
// destory workervm to release mem.
|
||||
thread_->SetReadyForGCIterating(false);
|
||||
sHeap->CollectGarbage(thread_, TriggerGCType::SHARED_GC, GCReason::WORKER_DESTRUCTION);
|
||||
}
|
||||
|
||||
if (debuggerManager_ != nullptr) {
|
||||
chunk_.Delete(debuggerManager_);
|
||||
debuggerManager_ = nullptr;
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
||||
@ -518,9 +523,9 @@ public:
|
||||
return enableLazyBuiltins_;
|
||||
}
|
||||
|
||||
void SetReadyForGCIterating()
|
||||
void SetReadyForGCIterating(bool flag)
|
||||
{
|
||||
readyForGCIterating_ = true;
|
||||
readyForGCIterating_ = flag;
|
||||
}
|
||||
|
||||
bool ReadyForGCIterating() const
|
||||
|
@ -71,6 +71,8 @@ const char *GCStats::GCReasonToString()
|
||||
return "Switch to background";
|
||||
case GCReason::EXTERNAL_TRIGGER:
|
||||
return "Externally triggered";
|
||||
case GCReason::WORKER_DESTRUCTION:
|
||||
return "Worker Destruction";
|
||||
default:
|
||||
return "Other";
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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,40 @@ 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() * 2); // 2: double
|
||||
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 +126,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 +194,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 +308,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()) {}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
});
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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_;
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ namespace panda::ecmascript {
|
||||
using PGOProfilerManager = pgo::PGOProfilerManager;
|
||||
|
||||
int32_t Runtime::vmCount_ = 0;
|
||||
int32_t Runtime::destroyCount_ = 0;
|
||||
bool Runtime::firstVmCreated_ = false;
|
||||
Mutex *Runtime::vmCreationLock_ = new Mutex();
|
||||
Runtime *Runtime::instance_ = nullptr;
|
||||
|
@ -46,6 +46,11 @@ public:
|
||||
void ResumeAll(JSThread *current);
|
||||
void IterateSerializeRoot(const RootVisitor &v);
|
||||
|
||||
JSThread *GetMainThread() const
|
||||
{
|
||||
return mainThread_;
|
||||
}
|
||||
|
||||
MutatorLock *GetMutatorLock()
|
||||
{
|
||||
return &mutatorLock_;
|
||||
@ -101,7 +106,21 @@ public:
|
||||
serializeDataIndexVector_.emplace_back(index);
|
||||
}
|
||||
|
||||
static bool SharedGCRequest()
|
||||
{
|
||||
LockHolder lock(*vmCreationLock_);
|
||||
destroyCount_++;
|
||||
if (destroyCount_ == WORKER_DESTRUCTION_COUNT || vmCount_ < MIN_GC_TRIGGER_VM_COUNT) {
|
||||
destroyCount_ = 0;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr int32_t WORKER_DESTRUCTION_COUNT = 3;
|
||||
static constexpr int32_t MIN_GC_TRIGGER_VM_COUNT = 4;
|
||||
Runtime() = default;
|
||||
~Runtime() = default;
|
||||
void SuspendAllThreadsImpl(JSThread *current);
|
||||
@ -140,6 +159,7 @@ private:
|
||||
|
||||
// Runtime instance and VMs creation.
|
||||
static int32_t vmCount_;
|
||||
static int32_t destroyCount_;
|
||||
static bool firstVmCreated_;
|
||||
static Mutex *vmCreationLock_;
|
||||
static Runtime *instance_;
|
||||
|
Loading…
Reference in New Issue
Block a user