mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-23 18:20:04 +00:00
Add force expand interface
issue:https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I7S293?from=project-issue Signed-off-by: wuwanqi <wuwanqi2@huawei.com> Change-Id: I8d46728c381a956d3a14f036fe4c03ad4d0b4c8b
This commit is contained in:
parent
f600731f0a
commit
1f9e21a744
4
BUILD.gn
4
BUILD.gn
@ -931,6 +931,10 @@ ohos_source_set("libark_jsruntime_set") {
|
||||
"/system/lib64/${arkcompiler_relative_lib_path}/lib_ark_builtins.d.abc"
|
||||
defines += [ "TARGET_BUILTINS_DTS_PATH=\"${target_builtins_dts_path}\"" ]
|
||||
|
||||
if (current_cpu == "arm64") {
|
||||
defines += [ "ENABLE_POSTFORK_FORCEEXPAND" ]
|
||||
}
|
||||
|
||||
sources = ecma_source
|
||||
sources += ecma_profiler_source
|
||||
sources += ecma_debugger_source
|
||||
|
@ -143,6 +143,9 @@ void EcmaVM::PostFork()
|
||||
heap_->SetHeapMode(HeapMode::SHARE);
|
||||
GetAssociatedJSThread()->SetThreadId();
|
||||
heap_->EnableParallelGC();
|
||||
#ifdef ENABLE_POSTFORK_FORCEEXPAND
|
||||
heap_->NotifyPostFork();
|
||||
#endif
|
||||
}
|
||||
|
||||
EcmaVM::EcmaVM(JSRuntimeOptions options, EcmaParamConfiguration config)
|
||||
|
@ -726,8 +726,9 @@ bool Heap::CheckAndTriggerOldGC(size_t size)
|
||||
if (isFullMarking && oldSpace_->GetOvershootSize() == 0) {
|
||||
oldSpace_->SetOvershootSize(GetEcmaVM()->GetEcmaParamConfiguration().GetOldSpaceOvershootSize());
|
||||
}
|
||||
if (isNativeSizeLargeTrigger || OldSpaceExceedLimit() || OldSpaceExceedCapacity(size) ||
|
||||
GetHeapObjectSize() > globalSpaceAllocLimit_ + oldSpace_->GetOvershootSize()) {
|
||||
if ((isNativeSizeLargeTrigger || OldSpaceExceedLimit() || OldSpaceExceedCapacity(size) ||
|
||||
GetHeapObjectSize() > globalSpaceAllocLimit_ + oldSpace_->GetOvershootSize()) &&
|
||||
!NeedStopCollection()) {
|
||||
CollectGarbage(TriggerGCType::OLD_GC, GCReason::ALLOCATION_LIMIT);
|
||||
if (!oldGCRequested_) {
|
||||
return true;
|
||||
@ -853,8 +854,7 @@ void Heap::TryTriggerIncrementalMarking()
|
||||
|
||||
double oldSpaceRemainSize = (oldSpaceAllocToLimitDuration - oldSpaceMarkDuration) * oldSpaceAllocSpeed;
|
||||
// mark finished before allocate limit
|
||||
if ((oldSpaceRemainSize > 0 && oldSpaceRemainSize < DEFAULT_REGION_SIZE) ||
|
||||
GetHeapObjectSize() >= globalSpaceAllocLimit_) {
|
||||
if ((oldSpaceRemainSize < DEFAULT_REGION_SIZE) || GetHeapObjectSize() >= globalSpaceAllocLimit_) {
|
||||
// The object allocated in incremental marking should lower than limit,
|
||||
// otherwise select trigger concurrent mark.
|
||||
size_t allocateSize = oldSpaceAllocSpeed * oldSpaceMarkDuration;
|
||||
@ -1112,6 +1112,74 @@ void Heap::NotifyMemoryPressure(bool inHighMemoryPressure)
|
||||
}
|
||||
}
|
||||
|
||||
void Heap::NotifyFinishColdStart(bool isMainThread)
|
||||
{
|
||||
{
|
||||
os::memory::LockHolder holder(finishColdStartMutex_);
|
||||
if (!onStartupEvent_) {
|
||||
return;
|
||||
}
|
||||
|
||||
// set overshoot size to increase gc threashold larger 8MB than current heap size.
|
||||
int64_t semiRemainSize = GetNewSpace()->GetInitialCapacity() - GetNewSpace()->GetCommittedSize();
|
||||
int64_t overshootSize = GetEcmaVM()->GetEcmaParamConfiguration().GetOldSpaceOvershootSize() - semiRemainSize;
|
||||
// overshoot size should be larger than 0.
|
||||
GetNewSpace()->SetOverShootSize(std::max(overshootSize, (int64_t)0));
|
||||
GetNewSpace()->SetWaterLineWithoutGC();
|
||||
onStartupEvent_ = false;
|
||||
}
|
||||
|
||||
if (isMainThread) {
|
||||
markType_ = MarkType::MARK_FULL;
|
||||
TriggerConcurrentMarking();
|
||||
}
|
||||
}
|
||||
|
||||
void Heap::NotifyFinishColdStartSoon()
|
||||
{
|
||||
if (!onStartupEvent_) {
|
||||
return;
|
||||
}
|
||||
|
||||
// post 2s task
|
||||
Taskpool::GetCurrentTaskpool()->PostTask(
|
||||
std::make_unique<FinishColdStartTask>(GetJSThread()->GetThreadId(), this));
|
||||
}
|
||||
|
||||
void Heap::NotifyHighSensitive(bool isStart)
|
||||
{
|
||||
onHighSensitiveEvent_ = isStart;
|
||||
if (!onHighSensitiveEvent_ && !onStartupEvent_) {
|
||||
// set overshoot size to increase gc threashold larger 8MB than current heap size.
|
||||
int64_t semiRemainSize = GetNewSpace()->GetInitialCapacity() - GetNewSpace()->GetCommittedSize();
|
||||
int64_t overshootSize = GetEcmaVM()->GetEcmaParamConfiguration().GetOldSpaceOvershootSize() - semiRemainSize;
|
||||
// overshoot size should be larger than 0.
|
||||
GetNewSpace()->SetOverShootSize(std::max(overshootSize, (int64_t)0));
|
||||
GetNewSpace()->SetWaterLineWithoutGC();
|
||||
|
||||
TryTriggerIncrementalMarking();
|
||||
TryTriggerIdleCollection();
|
||||
TryTriggerConcurrentMarking();
|
||||
}
|
||||
}
|
||||
|
||||
bool Heap::NeedStopCollection()
|
||||
{
|
||||
if (!InSensitiveStatus()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GetHeapObjectSize() < ecmaVm_->GetEcmaParamConfiguration().GetMaxHeapSize() -
|
||||
ecmaVm_->GetEcmaParamConfiguration().GetOldSpaceOvershootSize()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
GetNewSpace()->SetOverShootSize(
|
||||
GetNewSpace()->GetCommittedSize() - GetNewSpace()->GetInitialCapacity() +
|
||||
ecmaVm_->GetEcmaParamConfiguration().GetOldSpaceOvershootSize());
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Heap::CheckCanDistributeTask()
|
||||
{
|
||||
os::memory::LockHolder holder(waitTaskFinishedMutex_);
|
||||
@ -1167,6 +1235,13 @@ bool Heap::AsyncClearTask::Run([[maybe_unused]] uint32_t threadIndex)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Heap::FinishColdStartTask::Run([[maybe_unused]] uint32_t threadIndex)
|
||||
{
|
||||
usleep(2000000); // 2000000 means 2s
|
||||
heap_->NotifyFinishColdStart(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t Heap::GetArrayBufferSize() const
|
||||
{
|
||||
size_t result = 0;
|
||||
|
@ -224,6 +224,17 @@ public:
|
||||
return memController_;
|
||||
}
|
||||
|
||||
bool InSensitiveStatus() const
|
||||
{
|
||||
return onHighSensitiveEvent_ || onStartupEvent_;
|
||||
}
|
||||
|
||||
void NotifyPostFork()
|
||||
{
|
||||
os::memory::LockHolder holder(finishColdStartMutex_);
|
||||
onStartupEvent_ = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* For object allocations.
|
||||
*/
|
||||
@ -405,6 +416,19 @@ public:
|
||||
|
||||
void ClearIdleTask();
|
||||
|
||||
bool IsEmptyIdleTask() const
|
||||
{
|
||||
return idleTask_ == IdleTaskType::NO_TASK;
|
||||
}
|
||||
|
||||
void NotifyFinishColdStart(bool isMainThread = true);
|
||||
|
||||
void NotifyFinishColdStartSoon();
|
||||
|
||||
void NotifyHighSensitive(bool isStart);
|
||||
|
||||
bool NeedStopCollection();
|
||||
|
||||
#if defined(ECMASCRIPT_SUPPORT_HEAPPROFILER)
|
||||
void StartHeapTracking()
|
||||
{
|
||||
@ -587,6 +611,19 @@ private:
|
||||
TriggerGCType gcType_;
|
||||
};
|
||||
|
||||
class FinishColdStartTask : public Task {
|
||||
public:
|
||||
FinishColdStartTask(int32_t id, Heap *heap)
|
||||
: Task(id), heap_(heap) {}
|
||||
~FinishColdStartTask() override = default;
|
||||
bool Run(uint32_t threadIndex) override;
|
||||
|
||||
NO_COPY_SEMANTIC(FinishColdStartTask);
|
||||
NO_MOVE_SEMANTIC(FinishColdStartTask);
|
||||
private:
|
||||
Heap *heap_;
|
||||
};
|
||||
|
||||
EcmaVM *ecmaVm_ {nullptr};
|
||||
JSThread *thread_ {nullptr};
|
||||
|
||||
@ -683,6 +720,7 @@ private:
|
||||
uint32_t maxMarkTaskCount_ {0};
|
||||
// parallel evacuator task number.
|
||||
uint32_t maxEvacuateTaskCount_ {0};
|
||||
os::memory::Mutex finishColdStartMutex_;
|
||||
os::memory::Mutex waitTaskFinishedMutex_;
|
||||
os::memory::ConditionVariable waitTaskFinishedCV_;
|
||||
|
||||
@ -700,6 +738,8 @@ private:
|
||||
bool inBackground_ {false};
|
||||
|
||||
IdleNotifyStatusCallback notifyIdleStatusCallback {nullptr};
|
||||
bool onHighSensitiveEvent_ {false};
|
||||
bool onStartupEvent_ {false};
|
||||
|
||||
IdleTaskType idleTask_ {IdleTaskType::NO_TASK};
|
||||
float idlePredictDuration_ {0.0f};
|
||||
|
@ -43,13 +43,13 @@ uintptr_t LinearSpace::Allocate(size_t size, bool isPromoted)
|
||||
return object;
|
||||
}
|
||||
if (Expand(isPromoted)) {
|
||||
if (!isPromoted) {
|
||||
if (!isPromoted && !heap_->NeedStopCollection()) {
|
||||
heap_->TryTriggerIncrementalMarking();
|
||||
heap_->TryTriggerIdleCollection();
|
||||
heap_->TryTriggerConcurrentMarking();
|
||||
}
|
||||
object = allocator_.Allocate(size);
|
||||
} else if (heap_->GetJSThread()->IsMarking()) {
|
||||
} else if (heap_->GetJSThread()->IsMarking() || !heap_->IsEmptyIdleTask()) {
|
||||
// Temporary adjust semi space capacity
|
||||
if (heap_->IsFullMark()) {
|
||||
overShootSize_ = heap_->GetOldSpace()->GetMaximumCapacity() - heap_->GetOldSpace()->GetInitialCapacity();
|
||||
@ -71,7 +71,8 @@ uintptr_t LinearSpace::Allocate(size_t size, bool isPromoted)
|
||||
|
||||
bool LinearSpace::Expand(bool isPromoted)
|
||||
{
|
||||
if (committedSize_ >= initialCapacity_ + overShootSize_ + outOfMemoryOvershootSize_) {
|
||||
if (committedSize_ >= initialCapacity_ + overShootSize_ + outOfMemoryOvershootSize_ &&
|
||||
!heap_->NeedStopCollection()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -221,6 +222,23 @@ void SemiSpace::SetWaterLine()
|
||||
}
|
||||
}
|
||||
|
||||
void SemiSpace::SetWaterLineWithoutGC()
|
||||
{
|
||||
waterLine_ = allocator_.GetTop();
|
||||
Region *last = GetCurrentRegion();
|
||||
if (last != nullptr) {
|
||||
last->SetGCFlag(RegionGCFlags::HAS_AGE_MARK);
|
||||
|
||||
EnumerateRegions([&last](Region *current) {
|
||||
if (current != last) {
|
||||
current->SetGCFlag(RegionGCFlags::BELOW_AGE_MARK);
|
||||
}
|
||||
});
|
||||
survivalObjectSize_ += allocateAfterLastGC_;
|
||||
}
|
||||
allocateAfterLastGC_ = 0;
|
||||
}
|
||||
|
||||
size_t SemiSpace::GetHeapObjectSize() const
|
||||
{
|
||||
return survivalObjectSize_ + allocateAfterLastGC_;
|
||||
|
@ -68,6 +68,7 @@ public:
|
||||
void SetOverShootSize(size_t size);
|
||||
bool AdjustCapacity(size_t allocatedSizeSinceGC);
|
||||
void SetWaterLine();
|
||||
void SetWaterLineWithoutGC();
|
||||
|
||||
uintptr_t GetWaterLine() const
|
||||
{
|
||||
|
@ -551,7 +551,7 @@ void LocalSpace::Stop()
|
||||
}
|
||||
}
|
||||
|
||||
uintptr_t NonMovableSpace::CheckAndAllocate(size_t size)
|
||||
uintptr_t NonMovableSpace::CheckAndAllocate(size_t size)
|
||||
{
|
||||
if (maximumCapacity_ == committedSize_ && GetHeapObjectSize() > MAX_NONMOVABLE_LIVE_OBJ_SIZE &&
|
||||
!heap_->GetOldGCRequested())
|
||||
|
@ -270,6 +270,20 @@ void DFXJSNApi::NotifyMemoryPressure(EcmaVM *vm, bool inHighMemoryPressure)
|
||||
const_cast<ecmascript::Heap *>(vm->GetHeap())->NotifyMemoryPressure(inHighMemoryPressure);
|
||||
}
|
||||
|
||||
void DFXJSNApi::NotifyFinishColdStart(EcmaVM *vm, bool isConvinced)
|
||||
{
|
||||
if (isConvinced) {
|
||||
const_cast<ecmascript::Heap *>(vm->GetHeap())->NotifyFinishColdStart();
|
||||
} else {
|
||||
const_cast<ecmascript::Heap *>(vm->GetHeap())->NotifyFinishColdStartSoon();
|
||||
}
|
||||
}
|
||||
|
||||
void DFXJSNApi::NotifyHighSensitive(EcmaVM *vm, bool isStart)
|
||||
{
|
||||
const_cast<ecmascript::Heap *>(vm->GetHeap())->NotifyHighSensitive(isStart);
|
||||
}
|
||||
|
||||
bool DFXJSNApi::StopCpuProfilerForColdStart([[maybe_unused]] const EcmaVM *vm)
|
||||
{
|
||||
#if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
|
||||
|
@ -75,6 +75,8 @@ public:
|
||||
static void NotifyIdleStatusControl(const EcmaVM *vm, std::function<void(bool)> callback);
|
||||
static void NotifyIdleTime(const EcmaVM *vm, int idleMicroSec);
|
||||
static void NotifyMemoryPressure(EcmaVM *vm, bool inHighMemoryPressure);
|
||||
static void NotifyFinishColdStart(EcmaVM *vm, bool isConvinced);
|
||||
static void NotifyHighSensitive(EcmaVM *vm, bool isStart);
|
||||
static bool BuildJsStackInfoList(const EcmaVM *hostVm, uint32_t tid, std::vector<JsFrameInfo>& jsFrames);
|
||||
|
||||
// cpuprofiler
|
||||
|
@ -307,6 +307,61 @@ HWTEST_F_L0(GCTest, ArkToolsForceFullGC)
|
||||
ASSERT_TRUE(thread->GetEcmaVM()->GetHeap()->GetCommittedSize() < newSize);
|
||||
}
|
||||
|
||||
HWTEST_F_L0(GCTest, ColdStartForceExpand)
|
||||
{
|
||||
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
|
||||
size_t originalHeapSize = heap->GetCommittedSize();
|
||||
heap->GetConcurrentMarker()->ConfigConcurrentMark(false);
|
||||
heap->NotifyPostFork();
|
||||
heap->NotifyFinishColdStartSoon();
|
||||
{
|
||||
[[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread);
|
||||
for (int i = 0; i < 500; i++) {
|
||||
[[maybe_unused]] JSHandle<TaggedArray> array = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(
|
||||
10 * 1024, JSTaggedValue::Hole(), MemSpaceType::SEMI_SPACE);
|
||||
}
|
||||
}
|
||||
size_t expandHeapSize = thread->GetEcmaVM()->GetHeap()->GetCommittedSize();
|
||||
usleep(2500000);
|
||||
{
|
||||
[[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread);
|
||||
for (int i = 0; i < 100; i++) {
|
||||
[[maybe_unused]] JSHandle<TaggedArray> array = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(
|
||||
10 * 1024, JSTaggedValue::Hole(), MemSpaceType::SEMI_SPACE);
|
||||
}
|
||||
}
|
||||
size_t newSize = thread->GetEcmaVM()->GetHeap()->GetCommittedSize();
|
||||
EXPECT_TRUE(originalHeapSize < expandHeapSize);
|
||||
EXPECT_TRUE(expandHeapSize > newSize);
|
||||
}
|
||||
|
||||
HWTEST_F_L0(GCTest, HighSensitiveForceExpand)
|
||||
{
|
||||
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
|
||||
size_t originalHeapSize = heap->GetCommittedSize();
|
||||
heap->GetConcurrentMarker()->ConfigConcurrentMark(false);
|
||||
heap->NotifyHighSensitive(true);
|
||||
{
|
||||
[[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread);
|
||||
for (int i = 0; i < 500; i++) {
|
||||
[[maybe_unused]] JSHandle<TaggedArray> array = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(
|
||||
10 * 1024, JSTaggedValue::Hole(), MemSpaceType::SEMI_SPACE);
|
||||
}
|
||||
}
|
||||
size_t expandHeapSize = thread->GetEcmaVM()->GetHeap()->GetCommittedSize();
|
||||
const_cast<Heap *>(thread->GetEcmaVM()->GetHeap())->NotifyHighSensitive(false);
|
||||
{
|
||||
[[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread);
|
||||
for (int i = 0; i < 100; i++) {
|
||||
[[maybe_unused]] JSHandle<TaggedArray> array = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(
|
||||
10 * 1024, JSTaggedValue::Hole(), MemSpaceType::SEMI_SPACE);
|
||||
}
|
||||
}
|
||||
size_t newSize = thread->GetEcmaVM()->GetHeap()->GetCommittedSize();
|
||||
EXPECT_TRUE(originalHeapSize < expandHeapSize);
|
||||
EXPECT_TRUE(expandHeapSize > newSize);
|
||||
}
|
||||
|
||||
HWTEST_F_L0(GCTest, NoFullConcurrentMarkOldGCTrigger)
|
||||
{
|
||||
#ifdef NDEBUG
|
||||
|
Loading…
Reference in New Issue
Block a user