From 4198c6add124f7b4db09d00fc97efc6349f3c817 Mon Sep 17 00:00:00 2001 From: lukai Date: Wed, 15 Jun 2022 11:23:16 +0800 Subject: [PATCH] adjust pool size and related vm-memory according to physical memory issue: https://gitee.com/openharmony/ark_js_runtime/issues/I5CCG0?from=project-issue Signed-off-by: lukai Change-Id: I46bf3a11ef509ece55b45edc92bb7cb68c100dfa --- ecmascript/ecma_param_configuration.h | 149 ++++++++++++++++++-- ecmascript/ecma_vm.cpp | 9 +- ecmascript/ecma_vm.h | 12 +- ecmascript/js_runtime_options.h | 12 ++ ecmascript/js_thread.cpp | 8 +- ecmascript/mem/heap.cpp | 44 +++--- ecmascript/mem/linear_space.cpp | 2 +- ecmascript/mem/mem.h | 19 +-- ecmascript/mem/mem_controller.cpp | 8 +- ecmascript/mem/mem_controller.h | 1 + ecmascript/mem/mem_map_allocator.cpp | 9 +- ecmascript/mem/mem_map_allocator.h | 22 +++ ecmascript/mem/space.cpp | 2 +- ecmascript/napi/include/jsnapi.h | 11 ++ ecmascript/napi/jsnapi.cpp | 10 +- ecmascript/snapshot/tests/snapshot_test.cpp | 5 +- ecmascript/tests/ecma_vm_test.cpp | 3 +- ecmascript/tests/huge_object_test.cpp | 6 +- ecmascript/tests/js_serializer_test.cpp | 3 +- 19 files changed, 270 insertions(+), 65 deletions(-) diff --git a/ecmascript/ecma_param_configuration.h b/ecmascript/ecma_param_configuration.h index 4cd3e720c6..8bdea1a2f7 100644 --- a/ecmascript/ecma_param_configuration.h +++ b/ecmascript/ecma_param_configuration.h @@ -19,17 +19,146 @@ #include "libpandabase/mem/mem.h" namespace panda::ecmascript { - // MEMEORY SIZE SHOULD ROUND UP TO 256KB - static constexpr size_t MAX_HEAP_SIZE = 256_MB; // Recommended range: 128-256MB - static constexpr size_t DEFAULT_SEMI_SPACE_SIZE = 2_MB; // Recommended range: 2-4MB - static constexpr size_t MAX_SEMI_SPACE_SIZE = 16_MB; // Recommended range: 2-16MB - static constexpr size_t DEFAULT_NONMOVABLE_SPACE_SIZE = 4_MB; // Recommended range: 4-8MB - static constexpr size_t DEFAULT_SNAPSHOT_SPACE_SIZE = 256_KB; - static constexpr size_t MAX_SNAPSHOT_SPACE_SIZE = 8_MB; - static constexpr size_t DEFAULT_MACHINECODE_SPACE_SIZE = 8_MB; +static constexpr size_t DEFAULT_HEAP_SIZE = 256_MB; // Recommended range: 128-256MB +static constexpr size_t DEFAULT_WORKER_HEAP_SIZE = 64_MB; // Recommended range: 64_MB - static constexpr size_t MIN_AllOC_LIMIT_GROWING_STEP = 8_MB; - static constexpr uint32_t MAX_STACK_SIZE = 512_KB; +class EcmaParamConfiguration { +public: + EcmaParamConfiguration(bool isWorker, size_t poolSize) + { + if (isWorker) { + maxHeapSize_ = DEFAULT_WORKER_HEAP_SIZE; + } else { + if (poolSize >= DEFAULT_HEAP_SIZE) { + maxHeapSize_ = DEFAULT_HEAP_SIZE; + } else { + maxHeapSize_ = poolSize; // pool is too small, no memory left for worker + } + } + Initialize(); + } + + void Initialize() + { + if (maxHeapSize_ < LOW_MEMORY) { + UNREACHABLE(); + } + if (maxHeapSize_ < MEDIUM_MEMORY) { // 64_MB ~ 128_MB + minSemiSpaceSize_ = 2_MB; + maxSemiSpaceSize_ = 4_MB; + defaultNonMovableSpaceSize_ = 2_MB; + defaultSnapshotSpaceSize_ = 512_KB; + defaultMachineCodeSpaceSize_ = 2_MB; + semiSpaceTriggerConcurrentMark_ = 1_MB; + semiSpaceOvershootSize_ = 2_MB; + minAllocLimitGrowingStep_ = 2_MB; + minGrowingStep_ = 4_MB; + maxStackSize_ = 512_KB; + } else if (maxHeapSize_ < HIGH_MEMORY) { // 128_MB ~ 256_MB + minSemiSpaceSize_ = 2_MB; + maxSemiSpaceSize_ = 8_MB; + defaultNonMovableSpaceSize_ = 4_MB; + defaultSnapshotSpaceSize_ = 512_KB; + defaultMachineCodeSpaceSize_ = 2_MB; + semiSpaceTriggerConcurrentMark_ = 1.5_MB; + semiSpaceOvershootSize_ = 2_MB; + minAllocLimitGrowingStep_ = 4_MB; + minGrowingStep_ = 8_MB; + maxStackSize_ = 512_KB; + } else { // 256_MB + minSemiSpaceSize_ = 2_MB; + maxSemiSpaceSize_ = 16_MB; + defaultNonMovableSpaceSize_ = 4_MB; + defaultSnapshotSpaceSize_ = 4_MB; + defaultMachineCodeSpaceSize_ = 8_MB; + semiSpaceTriggerConcurrentMark_ = 1.5_MB; + semiSpaceOvershootSize_ = 2_MB; + minAllocLimitGrowingStep_ = 8_MB; + minGrowingStep_ = 16_MB; + maxStackSize_ = 512_KB; + } + size_t half = 2; + defaultHugeObjectSpaceSize_ = maxHeapSize_ / half; + } + + size_t GetMaxHeapSize() const + { + return maxHeapSize_; + } + + size_t GetMinSemiSpaceSize() const + { + return minSemiSpaceSize_; + } + + size_t GetMaxSemiSpaceSize() const + { + return maxSemiSpaceSize_; + } + + size_t GetDefaultNonMovableSpaceSize() const + { + return defaultNonMovableSpaceSize_; + } + + size_t GetDefaultSnapshotSpaceSize() const + { + return defaultSnapshotSpaceSize_; + } + + size_t GetDefaultMachineCodeSpaceSize() const + { + return defaultMachineCodeSpaceSize_; + } + + size_t GetSemiSpaceTriggerConcurrentMark() const + { + return semiSpaceTriggerConcurrentMark_; + } + + size_t GetSemiSpaceOvershootSize() const + { + return semiSpaceOvershootSize_; + } + + size_t GetDefaultHugeObjectSpaceSize() const + { + return defaultHugeObjectSpaceSize_; + } + + size_t GetMinAllocLimitGrowingStep() const + { + return minAllocLimitGrowingStep_; + } + + size_t GetMinGrowingStep() const + { + return minGrowingStep_; + } + + uint32_t GetMaxStackSize() const + { + return maxStackSize_; + } + +private: + static constexpr size_t LOW_MEMORY = 64_MB; + static constexpr size_t MEDIUM_MEMORY = 128_MB; + static constexpr size_t HIGH_MEMORY = 256_MB; + + size_t maxHeapSize_ {0}; + size_t minSemiSpaceSize_ {0}; + size_t maxSemiSpaceSize_ {0}; + size_t defaultNonMovableSpaceSize_ {0}; + size_t defaultSnapshotSpaceSize_ {0}; + size_t defaultMachineCodeSpaceSize_ {0}; + size_t defaultHugeObjectSpaceSize_ {0}; + size_t semiSpaceTriggerConcurrentMark_ {0}; + size_t semiSpaceOvershootSize_ {0}; + size_t minAllocLimitGrowingStep_ {0}; + size_t minGrowingStep_ {0}; + uint32_t maxStackSize_ {0}; +}; } // namespace panda::ecmascript #endif // ECMASCRIPT_ECMA_PARAM_CONFIGURATION_H diff --git a/ecmascript/ecma_vm.cpp b/ecmascript/ecma_vm.cpp index 36cbe22bbd..389785e130 100644 --- a/ecmascript/ecma_vm.cpp +++ b/ecmascript/ecma_vm.cpp @@ -78,9 +78,9 @@ namespace panda::ecmascript { /* static */ -EcmaVM *EcmaVM::Create(const JSRuntimeOptions &options) +EcmaVM *EcmaVM::Create(const JSRuntimeOptions &options, EcmaParamConfiguration &config) { - auto vm = new EcmaVM(options); + auto vm = new EcmaVM(options, config); if (UNLIKELY(vm == nullptr)) { LOG_ECMA(ERROR) << "Failed to create jsvm"; return nullptr; @@ -102,12 +102,13 @@ bool EcmaVM::Destroy(EcmaVM *vm) return false; } -EcmaVM::EcmaVM(JSRuntimeOptions options) +EcmaVM::EcmaVM(JSRuntimeOptions options, EcmaParamConfiguration config) : stringTable_(new EcmaStringTable(this)), nativeAreaAllocator_(std::make_unique()), heapRegionAllocator_(std::make_unique()), chunk_(nativeAreaAllocator_.get()), - nativePointerList_(&chunk_) + nativePointerList_(&chunk_), + ecmaParamConfiguration_(std::move(config)) { options_ = std::move(options); icEnabled_ = options_.EnableIC(); diff --git a/ecmascript/ecma_vm.h b/ecmascript/ecma_vm.h index 13677dedca..eba22017e1 100644 --- a/ecmascript/ecma_vm.h +++ b/ecmascript/ecma_vm.h @@ -87,11 +87,11 @@ using ResolvePathCallback = std::function GetGlobalEnv() const; JSHandle GetMicroJobQueue() const; @@ -441,6 +446,9 @@ private: // CJS resolve path Callbacks ResolvePathCallback resolvePathCallback_ {nullptr}; + // vm parameter configurations + EcmaParamConfiguration ecmaParamConfiguration_; + friend class Snapshot; friend class SnapshotProcessor; friend class ObjectFactory; diff --git a/ecmascript/js_runtime_options.h b/ecmascript/js_runtime_options.h index 8553997e40..c6751e1105 100644 --- a/ecmascript/js_runtime_options.h +++ b/ecmascript/js_runtime_options.h @@ -354,6 +354,16 @@ public: return heap_size_limit_.WasSet(); } + void SetIsWorker(bool isWorker) + { + isWorker_.SetValue(isWorker); + } + + bool IsWorker() const + { + return isWorker_.GetValue(); + } + bool EnableIC() const { return enableIC_.GetValue(); @@ -508,6 +518,8 @@ private: R"(enable statistics of runtime state. Default: false)"}; PandArg logTypeInfer_ {"log-Type-Infer", false, R"(print aot type infer log. Default: false)"}; + PandArg isWorker_ {"IsWorker", false, + R"(whether is worker vm)"}; }; } // namespace panda::ecmascript diff --git a/ecmascript/js_thread.cpp b/ecmascript/js_thread.cpp index 9ae09ffcdf..58b43f0a83 100644 --- a/ecmascript/js_thread.cpp +++ b/ecmascript/js_thread.cpp @@ -34,9 +34,10 @@ JSThread *JSThread::Create(EcmaVM *vm) jsThread->nativeAreaAllocator_ = vm->GetNativeAreaAllocator(); jsThread->heapRegionAllocator_ = vm->GetHeapRegionAllocator(); // algin with 16 + size_t maxStackSize = vm->GetEcmaParamConfiguration().GetMaxStackSize(); jsThread->glueData_.frameBase_ = static_cast( - vm->GetNativeAreaAllocator()->Allocate(sizeof(JSTaggedType) * MAX_STACK_SIZE)); - jsThread->glueData_.currentFrame_ = jsThread->glueData_.frameBase_ + MAX_STACK_SIZE; + vm->GetNativeAreaAllocator()->Allocate(sizeof(JSTaggedType) * maxStackSize)); + jsThread->glueData_.currentFrame_ = jsThread->glueData_.frameBase_ + maxStackSize; EcmaInterpreter::InitStackFrame(jsThread); return jsThread; } @@ -60,7 +61,8 @@ JSThread::~JSThread() handleScopeStorageNext_ = handleScopeStorageEnd_ = nullptr; GetEcmaVM()->GetChunk()->Delete(globalStorage_); - GetNativeAreaAllocator()->Free(glueData_.frameBase_, sizeof(JSTaggedType) * MAX_STACK_SIZE); + GetNativeAreaAllocator()->Free(glueData_.frameBase_, sizeof(JSTaggedType) * + vm_->GetEcmaParamConfiguration().GetMaxStackSize()); glueData_.frameBase_ = nullptr; nativeAreaAllocator_ = nullptr; heapRegionAllocator_ = nullptr; diff --git a/ecmascript/mem/heap.cpp b/ecmascript/mem/heap.cpp index 7cf3dcf458..1f4492149b 100644 --- a/ecmascript/mem/heap.cpp +++ b/ecmascript/mem/heap.cpp @@ -51,9 +51,10 @@ Heap::Heap(EcmaVM *ecmaVm) : ecmaVm_(ecmaVm), thread_(ecmaVm->GetJSThread()), void Heap::Initialize() { memController_ = new MemController(this); - - size_t minSemiSpaceCapacity = std::max(DEFAULT_SEMI_SPACE_SIZE, CONSTRAINT_MIN_SEMI_SPACE_SIZE); - size_t maxSemiSpaceCapacity = std::min(MAX_SEMI_SPACE_SIZE, CONSTRAINT_MAX_SEMI_SPACE_SIZE); + auto &config = ecmaVm_->GetEcmaParamConfiguration(); + size_t maxHeapSize = config.GetMaxHeapSize(); + size_t minSemiSpaceCapacity = config.GetMinSemiSpaceSize(); + size_t maxSemiSpaceCapacity = config.GetMaxSemiSpaceSize(); activeSemiSpace_ = new SemiSpace(this, minSemiSpaceCapacity, maxSemiSpaceCapacity); activeSemiSpace_->Restart(); activeSemiSpace_->SetWaterLine(); @@ -63,35 +64,37 @@ void Heap::Initialize() inactiveSemiSpace_ = new SemiSpace(this, minSemiSpaceCapacity, maxSemiSpaceCapacity); // not set up from space - size_t nonmovableSpaceCapacity = std::max(DEFAULT_NONMOVABLE_SPACE_SIZE, CONSTRAINT_MIN_NONMOVABLE_SPACE_SIZE); + size_t nonmovableSpaceCapacity = config.GetDefaultNonMovableSpaceSize(); if (ecmaVm_->GetJSOptions().WasSetMaxNonmovableSpaceCapacity()) { nonmovableSpaceCapacity = ecmaVm_->GetJSOptions().MaxNonmovableSpaceCapacity(); } nonMovableSpace_ = new NonMovableSpace(this, nonmovableSpaceCapacity, nonmovableSpaceCapacity); nonMovableSpace_->Initialize(); - size_t snapshotSpaceCapacity = std::max(DEFAULT_SNAPSHOT_SPACE_SIZE, CONSTRAINT_MIN_SNAPSHOT_SPACE_SIZE); - snapshotSpace_ = new SnapshotSpace(this, snapshotSpaceCapacity, MAX_SNAPSHOT_SPACE_SIZE); - size_t machineCodeSpaceCapacity = std::max(DEFAULT_MACHINECODE_SPACE_SIZE, CONSTRAINT_MIN_MACHINECODE_SPACE_SIZE); + size_t snapshotSpaceCapacity = config.GetDefaultSnapshotSpaceSize(); + snapshotSpace_ = new SnapshotSpace(this, snapshotSpaceCapacity, snapshotSpaceCapacity); + size_t machineCodeSpaceCapacity = config.GetDefaultMachineCodeSpaceSize(); machineCodeSpace_ = new MachineCodeSpace(this, machineCodeSpaceCapacity, machineCodeSpaceCapacity); machineCodeSpace_->Initialize(); size_t capacities = minSemiSpaceCapacity * 2 + nonmovableSpaceCapacity + snapshotSpaceCapacity + machineCodeSpaceCapacity; - if (MAX_HEAP_SIZE < capacities || MAX_HEAP_SIZE - capacities < MIN_OLD_SPACE_LIMIT) { - LOG_ECMA_MEM(FATAL) << "HeapSize is too small to initialize oldspace, heapSize = " << MAX_HEAP_SIZE; + if (maxHeapSize < capacities || maxHeapSize - capacities < MIN_OLD_SPACE_LIMIT) { + LOG_ECMA_MEM(FATAL) << "HeapSize is too small to initialize oldspace, heapSize = " << maxHeapSize; } - size_t oldSpaceCapacity = MAX_HEAP_SIZE - capacities; - globalSpaceAllocLimit_ = MAX_HEAP_SIZE - minSemiSpaceCapacity; + size_t oldSpaceCapacity = maxHeapSize - capacities; + globalSpaceAllocLimit_ = maxHeapSize - minSemiSpaceCapacity; oldSpace_ = new OldSpace(this, oldSpaceCapacity, oldSpaceCapacity); compressSpace_ = new OldSpace(this, oldSpaceCapacity, oldSpaceCapacity); oldSpace_->Initialize(); - hugeObjectSpace_ = new HugeObjectSpace(heapRegionAllocator_, oldSpaceCapacity, oldSpaceCapacity); + + size_t hugeObjectSpaceCapacity = config.GetDefaultHugeObjectSpaceSize(); + hugeObjectSpace_ = new HugeObjectSpace(heapRegionAllocator_, hugeObjectSpaceCapacity, hugeObjectSpaceCapacity); maxEvacuateTaskCount_ = Taskpool::GetCurrentTaskpool()->GetTotalThreadNum(); maxMarkTaskCount_ = std::min(ecmaVm_->GetJSOptions().GetGcThreadNum(), maxEvacuateTaskCount_ - 1); - LOG(INFO, RUNTIME) << "heap initialize: heap size = " << MAX_HEAP_SIZE + LOG(INFO, RUNTIME) << "heap initialize: heap size = " << maxHeapSize << ", semispace capacity = " << minSemiSpaceCapacity << ", nonmovablespace capacity = " << nonmovableSpaceCapacity << ", snapshotspace capacity = " << snapshotSpaceCapacity @@ -414,8 +417,9 @@ void Heap::AdjustOldSpaceLimit() if (oldSpaceLimitAdjusted_) { return; } + size_t minGrowingStep = ecmaVm_->GetEcmaParamConfiguration().GetMinGrowingStep(); size_t oldSpaceAllocLimit = GetOldSpace()->GetInitialCapacity(); - size_t newOldSpaceAllocLimit = std::max(oldSpace_->GetHeapObjectSize() + MIN_GROWING_STEP, + size_t newOldSpaceAllocLimit = std::max(oldSpace_->GetHeapObjectSize() + minGrowingStep, static_cast(oldSpaceAllocLimit * memController_->GetAverageSurvivalRate())); if (newOldSpaceAllocLimit <= oldSpaceAllocLimit) { GetOldSpace()->SetInitialCapacity(newOldSpaceAllocLimit); @@ -423,7 +427,7 @@ void Heap::AdjustOldSpaceLimit() oldSpaceLimitAdjusted_ = true; } - size_t newGlobalSpaceAllocLimit = std::max(GetHeapObjectSize() + MIN_GROWING_STEP, + size_t newGlobalSpaceAllocLimit = std::max(GetHeapObjectSize() + minGrowingStep, static_cast(globalSpaceAllocLimit_ * memController_->GetAverageSurvivalRate())); if (newGlobalSpaceAllocLimit < globalSpaceAllocLimit_) { globalSpaceAllocLimit_ = newGlobalSpaceAllocLimit; @@ -459,11 +463,12 @@ void Heap::RecomputeLimits() size_t newSpaceCapacity = activeSemiSpace_->GetInitialCapacity(); double growingFactor = memController_->CalculateGrowingFactor(gcSpeed, mutatorSpeed); - size_t maxOldSpaceCapacity = oldSpace_->GetMaximumCapacity(); + // newOldSpaceLimit should consider committedSize of hugeObjectSpace + size_t maxOldSpaceCapacity = oldSpace_->GetMaximumCapacity() - hugeObjectSpace_->GetCommittedSize(); auto newOldSpaceLimit = memController_->CalculateAllocLimit(oldSpaceSize, MIN_OLD_SPACE_LIMIT, maxOldSpaceCapacity, newSpaceCapacity, growingFactor); - size_t maxGlobalSize = MAX_HEAP_SIZE - newSpaceCapacity; - auto newGlobalSpaceLimit = memController_->CalculateAllocLimit(GetHeapObjectSize(), DEFAULT_HEAP_SIZE, + size_t maxGlobalSize = ecmaVm_->GetEcmaParamConfiguration().GetMaxHeapSize() - newSpaceCapacity; + auto newGlobalSpaceLimit = memController_->CalculateAllocLimit(GetHeapObjectSize(), MIN_HEAP_SIZE, maxGlobalSize, newSpaceCapacity, growingFactor); globalSpaceAllocLimit_ = newGlobalSpaceLimit; oldSpace_->SetInitialCapacity(newOldSpaceLimit); @@ -541,7 +546,8 @@ void Heap::TryTriggerConcurrentMarking() double newSpaceConcurrentMarkSpeed = memController_->GetNewSpaceConcurrentMarkSpeedPerMS(); if (newSpaceConcurrentMarkSpeed == 0 || newSpaceAllocSpeed == 0) { - if (activeSemiSpace_->GetCommittedSize() >= SEMI_SPACE_TRIGGER_CONCURRENT_MARK) { + auto &config = ecmaVm_->GetEcmaParamConfiguration(); + if (activeSemiSpace_->GetCommittedSize() >= config.GetSemiSpaceTriggerConcurrentMark()) { markType_ = MarkType::MARK_YOUNG; TriggerConcurrentMarking(); OPTIONAL_LOG(ecmaVm_, ERROR, ECMASCRIPT) << "Trigger the first semi mark" << fullGCRequested_; diff --git a/ecmascript/mem/linear_space.cpp b/ecmascript/mem/linear_space.cpp index 872f64bb4b..07b617e0ab 100644 --- a/ecmascript/mem/linear_space.cpp +++ b/ecmascript/mem/linear_space.cpp @@ -41,7 +41,7 @@ uintptr_t LinearSpace::Allocate(size_t size, bool isPromoted) object = allocator_.Allocate(size); } else if (heap_->GetJSThread()->IsMarking()) { // Temporary adjust semi space capacity - overShootSize_ = SEMI_SPACE_OVERSHOOT_SIZE; + overShootSize_ = heap_->GetEcmaVM()->GetEcmaParamConfiguration().GetSemiSpaceOvershootSize(); if (Expand(isPromoted)) { object = allocator_.Allocate(size); } diff --git a/ecmascript/mem/mem.h b/ecmascript/mem/mem.h index d10da9d629..d6bbc0879b 100644 --- a/ecmascript/mem/mem.h +++ b/ecmascript/mem/mem.h @@ -37,24 +37,19 @@ enum class MemAlignmentLog2 : uint8_t { MEM_ALIGN_REGION_LOG2 = 4, }; -static constexpr size_t SEMI_SPACE_TRIGGER_CONCURRENT_MARK = 1.5_MB; -static constexpr size_t SEMI_SPACE_OVERSHOOT_SIZE = 2_MB; - -static constexpr size_t CONSTRAINT_MIN_SEMI_SPACE_SIZE = 1_MB; -static constexpr size_t CONSTRAINT_MAX_SEMI_SPACE_SIZE = 16_MB; -static constexpr size_t CONSTRAINT_MIN_NONMOVABLE_SPACE_SIZE = 1_MB; -static constexpr size_t CONSTRAINT_MIN_SNAPSHOT_SPACE_SIZE = 256_KB; -static constexpr size_t CONSTRAINT_MIN_MACHINECODE_SPACE_SIZE = 4_MB; - -static constexpr size_t MIN_MEM_POOL_CAPACITY = 32_MB; +static constexpr size_t LARGE_POOL_SIZE = 480_MB; +static constexpr size_t MEDIUM_POOL_SIZE = 256_MB; +static constexpr size_t LOW_POOL_SIZE = 64_MB; +static constexpr size_t MIN_MEM_POOL_CAPACITY = 64_MB; static constexpr size_t PHY_SIZE_MULTIPLE = 4; +static constexpr size_t WORKER_NUM = 7; +static constexpr size_t STANDARD_POOL_SIZE = WORKER_NUM * DEFAULT_WORKER_HEAP_SIZE + DEFAULT_HEAP_SIZE; static constexpr size_t MIN_OLD_SPACE_LIMIT = 2_MB; -static constexpr size_t MIN_GROWING_STEP = 16_MB; static constexpr size_t REGION_SIZE_LOG2 = 18U; -static constexpr size_t DEFAULT_HEAP_SIZE = 5_MB; +static constexpr size_t MIN_HEAP_SIZE = 5_MB; static constexpr size_t DEFAULT_REGION_SIZE = 1U << REGION_SIZE_LOG2; static constexpr size_t DEFAULT_REGION_MASK = DEFAULT_REGION_SIZE - 1; diff --git a/ecmascript/mem/mem_controller.cpp b/ecmascript/mem/mem_controller.cpp index 49594d713e..61027aa681 100644 --- a/ecmascript/mem/mem_controller.cpp +++ b/ecmascript/mem/mem_controller.cpp @@ -20,19 +20,21 @@ #include "ecmascript/mem/parallel_evacuator.h" namespace panda::ecmascript { -MemController::MemController(Heap *heap) : heap_(heap), allocTimeMs_(GetSystemTimeInMs()) {} +MemController::MemController(Heap *heap) : heap_(heap), allocTimeMs_(GetSystemTimeInMs()) +{ + minAllocLimitGrowingStep_ = heap->GetEcmaVM()->GetEcmaParamConfiguration().GetMinAllocLimitGrowingStep(); +} double MemController::CalculateAllocLimit(size_t currentSize, size_t minSize, size_t maxSize, size_t newSpaceCapacity, double factor) const { const uint64_t limit = std::max(static_cast(currentSize * factor), - static_cast(currentSize) + MIN_AllOC_LIMIT_GROWING_STEP) + + static_cast(currentSize) + minAllocLimitGrowingStep_) + newSpaceCapacity; const uint64_t limitAboveMinSize = std::max(limit, minSize); const uint64_t halfToMaxSize = (static_cast(currentSize) + maxSize) / 2; auto result = static_cast(std::min(limitAboveMinSize, halfToMaxSize)); - // Avoid the limit is larger than maxSize - newSpaceCapacity. It may cause old space merge OOM. result = static_cast(std::min(result, maxSize)); return result; } diff --git a/ecmascript/mem/mem_controller.h b/ecmascript/mem/mem_controller.h index ca6b056861..55a45f7fde 100644 --- a/ecmascript/mem/mem_controller.h +++ b/ecmascript/mem/mem_controller.h @@ -135,6 +135,7 @@ private: const BytesAndDuration &initial, const double timeMs); Heap* heap_; + size_t minAllocLimitGrowingStep_ {0}; double gcStartTime_ {0.0}; double gcEndTime_ {0.0}; diff --git a/ecmascript/mem/mem_map_allocator.cpp b/ecmascript/mem/mem_map_allocator.cpp index 360450aa36..fcc1420720 100644 --- a/ecmascript/mem/mem_map_allocator.cpp +++ b/ecmascript/mem/mem_map_allocator.cpp @@ -127,6 +127,13 @@ void MemMapAllocator::AdapterSuitablePoolCapacity() long physSize = pages * pageSize; #endif capacity_ = std::max(physSize / PHY_SIZE_MULTIPLE, MIN_MEM_POOL_CAPACITY); - LOG(INFO, RUNTIME) << "Auto adapter memory pool capacity:" << capacity_; + if (capacity_ > LARGE_POOL_SIZE) { + capacity_ = std::max(capacity_, STANDARD_POOL_SIZE); + } else if (capacity_ >= MEDIUM_POOL_SIZE) { + capacity_ = std::min(capacity_, STANDARD_POOL_SIZE); + } else if (capacity_ >= LOW_POOL_SIZE) { + capacity_ = std::max(capacity_, 128_MB); + } + LOG(INFO, RUNTIME) << "Ark Auto adapter memory pool capacity:" << capacity_; } } // namespace panda::ecmascript diff --git a/ecmascript/mem/mem_map_allocator.h b/ecmascript/mem/mem_map_allocator.h index 77a0013d79..b49a56d719 100644 --- a/ecmascript/mem/mem_map_allocator.h +++ b/ecmascript/mem/mem_map_allocator.h @@ -216,6 +216,27 @@ public: memMapPool_.Finalize(); } + size_t GetCapacity() + { + return capacity_; + } + + void IncreaseAndCheckReserved(size_t size) + { + if (reserved_ + size > capacity_) { + LOG(ERROR, RUNTIME) << "pool is empty, reserved = " << reserved_ << ", capacity_ = " + << capacity_ << ", size = " << size; + } + reserved_ += size; + LOG(DEBUG, RUNTIME) << "Ark IncreaseAndCheckReserved reserved = " << reserved_ << ", capacity_ = " << capacity_; + } + + void DecreaseReserved(size_t size) + { + reserved_ -= size; + LOG(DEBUG, RUNTIME) << "Ark DecreaseReserved reserved = " << reserved_ << ", capacity_ = " << capacity_; + } + static MemMapAllocator *GetInstance() { static MemMapAllocator vmAllocator_; @@ -255,6 +276,7 @@ private: MemMapFreeList memMapFreeList_; std::atomic_size_t memMapTotalSize_ {0}; size_t capacity_ {0}; + size_t reserved_ {0}; }; } // namespace panda::ecmascript #endif // ECMASCRIPT_MEM_MEM_MAP_ALLOCATOR_H diff --git a/ecmascript/mem/space.cpp b/ecmascript/mem/space.cpp index 891842bae0..79a8bf6729 100644 --- a/ecmascript/mem/space.cpp +++ b/ecmascript/mem/space.cpp @@ -70,7 +70,7 @@ HugeObjectSpace::HugeObjectSpace(HeapRegionAllocator *heapRegionAllocator, uintptr_t HugeObjectSpace::Allocate(size_t objectSize, JSThread *thread) { - if (committedSize_ >= maximumCapacity_) { + if (committedSize_ + objectSize >= maximumCapacity_) { LOG_ECMA_MEM(INFO) << "Committed size " << committedSize_ << " of huge object space is too big."; return 0; } diff --git a/ecmascript/napi/include/jsnapi.h b/ecmascript/napi/include/jsnapi.h index 02b821bce5..8d6754e34c 100644 --- a/ecmascript/napi/include/jsnapi.h +++ b/ecmascript/napi/include/jsnapi.h @@ -943,6 +943,16 @@ public: asmOpcodeDisableRange_ = value; } + void SetIsWorker() + { + isWorker_ = true; + } + + bool GetIsWorker() const + { + return isWorker_; + } + private: std::string GetGcType() const { @@ -1051,6 +1061,7 @@ private: size_t gcThreadNum_ {DEFAULT_GC_THREAD_NUM}; size_t longPauseTime_ {DEFAULT_LONG_PAUSE_TIME}; bool enableAsmInterpreter_ {false}; + bool isWorker_ {false}; std::string asmOpcodeDisableRange_ {""}; friend JSNApi; }; diff --git a/ecmascript/napi/jsnapi.cpp b/ecmascript/napi/jsnapi.cpp index 205a5417d8..5391f59069 100644 --- a/ecmascript/napi/jsnapi.cpp +++ b/ecmascript/napi/jsnapi.cpp @@ -129,6 +129,7 @@ EcmaVM *JSNApi::CreateJSVM(const RuntimeOption &option) runtimeOptions.SetArkProperties(option.GetArkProperties()); runtimeOptions.SetLongPauseTime(option.GetLongPauseTime()); runtimeOptions.SetGcThreadNum(option.GetGcThreadNum()); + runtimeOptions.SetIsWorker(option.GetIsWorker()); // Mem runtimeOptions.SetHeapSizeLimit(option.GetGcPoolSize()); // asmInterpreter @@ -145,7 +146,6 @@ EcmaVM *JSNApi::CreateJSVM(const RuntimeOption &option) if (option.GetLogBufPrint() != nullptr) { Logger::SetMobileLogPrintEntryPointByPtr(reinterpret_cast(option.GetLogBufPrint())); } - runtimeOptions.SetEnableArkTools(option.GetEnableArkTools()); return CreateEcmaVM(runtimeOptions); } @@ -160,7 +160,11 @@ EcmaVM *JSNApi::CreateEcmaVM(const JSRuntimeOptions &options) initialize_ = true; } } - return EcmaVM::Create(options); + auto config = ecmascript::EcmaParamConfiguration(options.IsWorker(), + MemMapAllocator::GetInstance()->GetCapacity()); + LOG(INFO, RUNTIME) << "CreateEcmaVM: isWorker = " << options.IsWorker() << ", vmCount = " << vmCount_; + MemMapAllocator::GetInstance()->IncreaseAndCheckReserved(config.GetMaxHeapSize()); + return EcmaVM::Create(options, config); } void JSNApi::DestroyJSVM(EcmaVM *ecmaVm) @@ -169,6 +173,8 @@ void JSNApi::DestroyJSVM(EcmaVM *ecmaVm) if (!initialize_) { return; } + auto &config = ecmaVm->GetEcmaParamConfiguration(); + MemMapAllocator::GetInstance()->DecreaseReserved(config.GetMaxHeapSize()); EcmaVM::Destroy(ecmaVm); vmCount_--; if (vmCount_ <= 0) { diff --git a/ecmascript/snapshot/tests/snapshot_test.cpp b/ecmascript/snapshot/tests/snapshot_test.cpp index 3c06db8e46..d09d59ec47 100644 --- a/ecmascript/snapshot/tests/snapshot_test.cpp +++ b/ecmascript/snapshot/tests/snapshot_test.cpp @@ -254,13 +254,14 @@ HWTEST_F_L0(SnapshotTest, SerializeBuiltins) // generate builtins.snapshot file JSRuntimeOptions options1; options1.SetArkProperties(ArkProperties::ENABLE_SNAPSHOT_SERIALIZE); - EcmaVM *ecmaVm1 = EcmaVM::Create(options1); + auto config = ecmascript::EcmaParamConfiguration(false, MemMapAllocator::GetInstance()->GetCapacity()); + EcmaVM *ecmaVm1 = EcmaVM::Create(options1, config); EcmaVM::Destroy(ecmaVm1); // create EcmaVM use builtins deserialzie JSRuntimeOptions options2; options2.SetArkProperties(ArkProperties::ENABLE_SNAPSHOT_DESERIALIZE); - EcmaVM *ecmaVm2 = EcmaVM::Create(options2); + EcmaVM *ecmaVm2 = EcmaVM::Create(options2, config); EXPECT_TRUE(ecmaVm2->GetGlobalEnv()->GetClass()->GetObjectType() == JSType::GLOBAL_ENV); auto globalConst = const_cast(ecmaVm2->GetJSThread()->GlobalConstants()); size_t hclassEndIndex = globalConst->GetHClassEndIndex(); diff --git a/ecmascript/tests/ecma_vm_test.cpp b/ecmascript/tests/ecma_vm_test.cpp index 7ea08c4b50..3962a0d51b 100644 --- a/ecmascript/tests/ecma_vm_test.cpp +++ b/ecmascript/tests/ecma_vm_test.cpp @@ -59,7 +59,8 @@ HWTEST_F_L0(EcmaVMTest, CreateEcmaVMInTwoWays) options2.SetEnableCpuprofiler(true); options2.SetArkProperties(ArkProperties::GC_STATS_PRINT); // A non-production gc strategy. Prohibit stw-gc 10 times. - EcmaVM *ecmaVm2 = EcmaVM::Create(options2); + auto config = ecmascript::EcmaParamConfiguration(false, MemMapAllocator::GetInstance()->GetCapacity()); + EcmaVM *ecmaVm2 = EcmaVM::Create(options2, config); EXPECT_TRUE(ecmaVm1 != ecmaVm2); diff --git a/ecmascript/tests/huge_object_test.cpp b/ecmascript/tests/huge_object_test.cpp index 68d0ced640..82958c6d91 100644 --- a/ecmascript/tests/huge_object_test.cpp +++ b/ecmascript/tests/huge_object_test.cpp @@ -95,21 +95,21 @@ HWTEST_F_L0(HugeObjectTest, MultipleArrays) auto heap = ecmaVm->GetHeap(); { [[maybe_unused]] ecmascript::EcmaHandleScope scope(thread); - for (int i = 0; i <= 20; i++) { + for (int i = 0; i <= 14; i++) { JSHandle array1(thread, LargeArrayTestCreate(thread)); } } { [[maybe_unused]] ecmascript::EcmaHandleScope scope(thread); - for (int i = 0; i <= 20; i++) { + for (int i = 0; i <= 14; i++) { JSHandle array2(thread, LargeArrayTestCreate(thread)); } } { [[maybe_unused]] ecmascript::EcmaHandleScope scope(thread); - for (int i = 0; i <= 20; i++) { + for (int i = 0; i <= 14; i++) { JSHandle array2(thread, LargeArrayTestCreate(thread)); } } diff --git a/ecmascript/tests/js_serializer_test.cpp b/ecmascript/tests/js_serializer_test.cpp index 78d6cbbe88..24703b1c05 100644 --- a/ecmascript/tests/js_serializer_test.cpp +++ b/ecmascript/tests/js_serializer_test.cpp @@ -42,7 +42,8 @@ public: { JSRuntimeOptions options; options.SetEnableForceGC(true); - ecmaVm = EcmaVM::Create(options); + auto config = ecmascript::EcmaParamConfiguration(false, MemMapAllocator::GetInstance()->GetCapacity()); + ecmaVm = EcmaVM::Create(options, config); ecmaVm->SetEnableForceGC(true); EXPECT_TRUE(ecmaVm != nullptr) << "Cannot create Runtime"; thread = ecmaVm->GetJSThread();