14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License.
54514f5e3Sopenharmony_ci * You may obtain a copy of the License at
64514f5e3Sopenharmony_ci *
74514f5e3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84514f5e3Sopenharmony_ci *
94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and
134514f5e3Sopenharmony_ci * limitations under the License.
144514f5e3Sopenharmony_ci */
154514f5e3Sopenharmony_ci
164514f5e3Sopenharmony_ci#include "ecmascript/mem/mem_controller.h"
174514f5e3Sopenharmony_ci
184514f5e3Sopenharmony_ci#include "ecmascript/mem/concurrent_marker.h"
194514f5e3Sopenharmony_ci#include "ecmascript/mem/parallel_evacuator.h"
204514f5e3Sopenharmony_ci
214514f5e3Sopenharmony_cinamespace panda::ecmascript {
224514f5e3Sopenharmony_ciMemController::MemController(Heap *heap) : heap_(heap), allocTimeMs_(GetSystemTimeInMs())
234514f5e3Sopenharmony_ci{
244514f5e3Sopenharmony_ci    minAllocLimitGrowingStep_ = heap->GetEcmaVM()->GetEcmaParamConfiguration().GetMinAllocLimitGrowingStep();
254514f5e3Sopenharmony_ci}
264514f5e3Sopenharmony_ci
274514f5e3Sopenharmony_cisize_t MemController::CalculateAllocLimit(size_t currentSize, size_t minSize, size_t maxSize, size_t newSpaceCapacity,
284514f5e3Sopenharmony_ci                                          double factor) const
294514f5e3Sopenharmony_ci{
304514f5e3Sopenharmony_ci    const uint64_t limit = std::max(static_cast<uint64_t>(currentSize * factor),
314514f5e3Sopenharmony_ci                                    static_cast<uint64_t>(currentSize) + minAllocLimitGrowingStep_) +
324514f5e3Sopenharmony_ci                           newSpaceCapacity;
334514f5e3Sopenharmony_ci
344514f5e3Sopenharmony_ci    const uint64_t limitAboveMinSize = std::max<uint64_t>(limit, minSize);
354514f5e3Sopenharmony_ci    const uint64_t halfToMaxSize = (static_cast<uint64_t>(currentSize) + maxSize) / 2;
364514f5e3Sopenharmony_ci    size_t result = static_cast<size_t>(std::min(limitAboveMinSize, halfToMaxSize));
374514f5e3Sopenharmony_ci    result = static_cast<size_t>(std::min(result, maxSize));
384514f5e3Sopenharmony_ci    return result;
394514f5e3Sopenharmony_ci}
404514f5e3Sopenharmony_ci
414514f5e3Sopenharmony_cidouble MemController::CalculateGrowingFactor(double gcSpeed, double mutatorSpeed)
424514f5e3Sopenharmony_ci{
434514f5e3Sopenharmony_ci    double maxGrowingFactor = 4.0;
444514f5e3Sopenharmony_ci    double halfMaxGrowingFactor = 2.0;
454514f5e3Sopenharmony_ci    double minGrowingFactor = 1.3;
464514f5e3Sopenharmony_ci    double minimumFactor = 1.1;
474514f5e3Sopenharmony_ci    switch (heap_->GetMemGrowingType()) {
484514f5e3Sopenharmony_ci        case MemGrowingType::HIGH_THROUGHPUT:
494514f5e3Sopenharmony_ci            break;
504514f5e3Sopenharmony_ci        case MemGrowingType::CONSERVATIVE:
514514f5e3Sopenharmony_ci            minGrowingFactor = minimumFactor;
524514f5e3Sopenharmony_ci            maxGrowingFactor = halfMaxGrowingFactor;
534514f5e3Sopenharmony_ci            break;
544514f5e3Sopenharmony_ci        case MemGrowingType::PRESSURE:
554514f5e3Sopenharmony_ci            return minimumFactor;
564514f5e3Sopenharmony_ci        default:
574514f5e3Sopenharmony_ci            break;
584514f5e3Sopenharmony_ci    }
594514f5e3Sopenharmony_ci
604514f5e3Sopenharmony_ci    static constexpr double targetMutatorUtilization = 0.97;
614514f5e3Sopenharmony_ci    if (gcSpeed == 0 || mutatorSpeed == 0) {
624514f5e3Sopenharmony_ci        return maxGrowingFactor;
634514f5e3Sopenharmony_ci    }
644514f5e3Sopenharmony_ci
654514f5e3Sopenharmony_ci    const double speedRatio = gcSpeed / mutatorSpeed;
664514f5e3Sopenharmony_ci
674514f5e3Sopenharmony_ci    const double a = speedRatio * (1 - targetMutatorUtilization);
684514f5e3Sopenharmony_ci    const double b = speedRatio * (1 - targetMutatorUtilization) -  targetMutatorUtilization;
694514f5e3Sopenharmony_ci
704514f5e3Sopenharmony_ci    double factor = (a < b * maxGrowingFactor) ? a / b : maxGrowingFactor;
714514f5e3Sopenharmony_ci    factor = std::min(maxGrowingFactor, factor);
724514f5e3Sopenharmony_ci    factor = std::max(factor, minGrowingFactor);
734514f5e3Sopenharmony_ci    OPTIONAL_LOG(heap_->GetEcmaVM(), INFO) << "CalculateGrowingFactor gcSpeed"
744514f5e3Sopenharmony_ci        << gcSpeed << " mutatorSpeed" << mutatorSpeed << " factor" << factor;
754514f5e3Sopenharmony_ci    return factor;
764514f5e3Sopenharmony_ci}
774514f5e3Sopenharmony_ci
784514f5e3Sopenharmony_civoid MemController::StartCalculationBeforeGC()
794514f5e3Sopenharmony_ci{
804514f5e3Sopenharmony_ci    startCounter_++;
814514f5e3Sopenharmony_ci    if (startCounter_ != 1) {
824514f5e3Sopenharmony_ci        return;
834514f5e3Sopenharmony_ci    }
844514f5e3Sopenharmony_ci
854514f5e3Sopenharmony_ci    auto edenSpace = heap_->GetEdenSpace();
864514f5e3Sopenharmony_ci    size_t edenSpaceAllocBytesSinceGC = edenSpace->GetAllocatedSizeSinceGC(edenSpace->GetTop());
874514f5e3Sopenharmony_ci    // It's unnecessary to calculate newSpaceAllocAccumulatedSize. newSpaceAllocBytesSinceGC can be calculated directly.
884514f5e3Sopenharmony_ci    auto newSpace = heap_->GetNewSpace();
894514f5e3Sopenharmony_ci    size_t newSpaceAllocBytesSinceGC = newSpace->GetAllocatedSizeSinceGC(newSpace->GetTop());
904514f5e3Sopenharmony_ci    size_t hugeObjectAllocSizeSinceGC = heap_->GetHugeObjectSpace()->GetHeapObjectSize() - hugeObjectAllocSizeSinceGC_;
914514f5e3Sopenharmony_ci    size_t oldSpaceAllocAccumulatedSize = heap_->GetOldSpace()->GetTotalAllocatedSize();
924514f5e3Sopenharmony_ci    size_t nonMovableSpaceAllocAccumulatedSize = heap_->GetNonMovableSpace()->GetTotalAllocatedSize();
934514f5e3Sopenharmony_ci    size_t codeSpaceAllocAccumulatedSize = heap_->GetMachineCodeSpace()->GetTotalAllocatedSize();
944514f5e3Sopenharmony_ci    double currentTimeInMs = GetSystemTimeInMs();
954514f5e3Sopenharmony_ci    gcStartTime_ = currentTimeInMs;
964514f5e3Sopenharmony_ci    size_t oldSpaceAllocSize = oldSpaceAllocAccumulatedSize - oldSpaceAllocAccumulatedSize_;
974514f5e3Sopenharmony_ci    size_t nonMovableSpaceAllocSize = nonMovableSpaceAllocAccumulatedSize - nonMovableSpaceAllocAccumulatedSize_;
984514f5e3Sopenharmony_ci    size_t codeSpaceAllocSize = codeSpaceAllocAccumulatedSize - codeSpaceAllocAccumulatedSize_;
994514f5e3Sopenharmony_ci
1004514f5e3Sopenharmony_ci    double duration = currentTimeInMs - allocTimeMs_;
1014514f5e3Sopenharmony_ci    allocTimeMs_ = currentTimeInMs;
1024514f5e3Sopenharmony_ci    oldSpaceAllocAccumulatedSize_ = oldSpaceAllocAccumulatedSize;
1034514f5e3Sopenharmony_ci    nonMovableSpaceAllocAccumulatedSize_ = nonMovableSpaceAllocAccumulatedSize;
1044514f5e3Sopenharmony_ci    codeSpaceAllocAccumulatedSize_ = codeSpaceAllocAccumulatedSize;
1054514f5e3Sopenharmony_ci
1064514f5e3Sopenharmony_ci    allocDurationSinceGc_ += duration;
1074514f5e3Sopenharmony_ci
1084514f5e3Sopenharmony_ci    edenSpaceAllocSizeSinceGC_ += edenSpaceAllocBytesSinceGC;
1094514f5e3Sopenharmony_ci    newSpaceAllocSizeSinceGC_ += newSpaceAllocBytesSinceGC;
1104514f5e3Sopenharmony_ci    oldSpaceAllocSizeSinceGC_ += oldSpaceAllocSize;
1114514f5e3Sopenharmony_ci    oldSpaceAllocSizeSinceGC_ += hugeObjectAllocSizeSinceGC;
1124514f5e3Sopenharmony_ci    nonMovableSpaceAllocSizeSinceGC_ += nonMovableSpaceAllocSize;
1134514f5e3Sopenharmony_ci    codeSpaceAllocSizeSinceGC_ += codeSpaceAllocSize;
1144514f5e3Sopenharmony_ci
1154514f5e3Sopenharmony_ci    if (heap_->GetEcmaGCStats()->GetGCReason() != GCReason::IDLE) {
1164514f5e3Sopenharmony_ci        recordedIdleNewSpaceAllocations_.Push(MakeBytesAndDuration(
1174514f5e3Sopenharmony_ci            heap_->GetNewSpace()->GetHeapObjectSize() - newSpaceRecordLastTimeSizeIdle_,
1184514f5e3Sopenharmony_ci            currentTimeInMs - allocTimeMsIdle_));
1194514f5e3Sopenharmony_ci        recordedIdleOldSpaceAllocations_.Push(MakeBytesAndDuration(
1204514f5e3Sopenharmony_ci            heap_->GetOldSpace()->GetHeapObjectSize() - oldSpaceRecordLastTimeSizeIdle_,
1214514f5e3Sopenharmony_ci            currentTimeInMs - allocTimeMsIdle_));
1224514f5e3Sopenharmony_ci    }
1234514f5e3Sopenharmony_ci}
1244514f5e3Sopenharmony_ci
1254514f5e3Sopenharmony_civoid MemController::RecordAllocationForIdle()
1264514f5e3Sopenharmony_ci{
1274514f5e3Sopenharmony_ci    double currentTimeInMs = GetSystemTimeInMs();
1284514f5e3Sopenharmony_ci    size_t currentNewSpaceObjectSize = heap_->GetNewSpace()->GetHeapObjectSize();
1294514f5e3Sopenharmony_ci    size_t currentOldSpaceObjectSize = heap_->GetOldSpace()->GetHeapObjectSize();
1304514f5e3Sopenharmony_ci    double duration = currentTimeInMs - allocTimeMsIdle_;
1314514f5e3Sopenharmony_ci    allocTimeMsIdle_ = currentTimeInMs;
1324514f5e3Sopenharmony_ci    if (currentNewSpaceObjectSize < newSpaceRecordLastTimeSizeIdle_ ||
1334514f5e3Sopenharmony_ci        currentOldSpaceObjectSize < oldSpaceRecordLastTimeSizeIdle_) {
1344514f5e3Sopenharmony_ci        newSpaceRecordLastTimeSizeIdle_ = currentNewSpaceObjectSize;
1354514f5e3Sopenharmony_ci        oldSpaceRecordLastTimeSizeIdle_ = currentOldSpaceObjectSize;
1364514f5e3Sopenharmony_ci        return;
1374514f5e3Sopenharmony_ci    }
1384514f5e3Sopenharmony_ci
1394514f5e3Sopenharmony_ci    size_t newSpaceAllocSizeSinceIdle = currentNewSpaceObjectSize - newSpaceRecordLastTimeSizeIdle_;
1404514f5e3Sopenharmony_ci    newSpaceRecordLastTimeSizeIdle_ = currentNewSpaceObjectSize;
1414514f5e3Sopenharmony_ci    size_t oldSpaceAllocSizeSinceIdle = currentOldSpaceObjectSize - oldSpaceRecordLastTimeSizeIdle_;
1424514f5e3Sopenharmony_ci    oldSpaceRecordLastTimeSizeIdle_ = currentOldSpaceObjectSize;
1434514f5e3Sopenharmony_ci    recordedIdleNewSpaceAllocations_.Push(MakeBytesAndDuration(newSpaceAllocSizeSinceIdle, duration));
1444514f5e3Sopenharmony_ci    recordedIdleOldSpaceAllocations_.Push(MakeBytesAndDuration(oldSpaceAllocSizeSinceIdle, duration));
1454514f5e3Sopenharmony_ci}
1464514f5e3Sopenharmony_ci
1474514f5e3Sopenharmony_cibool MemController::CheckLowAllocationUsageState() const
1484514f5e3Sopenharmony_ci{
1494514f5e3Sopenharmony_ci    LOG_GC(DEBUG) << "local CheckLowAllocationUsageState NewSpaceAllocBytesPerMS:" <<
1504514f5e3Sopenharmony_ci        GetIdleNewSpaceAllocationThroughputPerMS() << ",OldSpaceAllocBytesPerMS:" <<
1514514f5e3Sopenharmony_ci        GetIdleOldSpaceAllocationThroughputPerMS();
1524514f5e3Sopenharmony_ci    return GetIdleNewSpaceAllocationThroughputPerMS() < LOW_ALLOCATION_RATE_PER_MS &&
1534514f5e3Sopenharmony_ci                GetIdleOldSpaceAllocationThroughputPerMS() < LOW_ALLOCATION_RATE_PER_MS;
1544514f5e3Sopenharmony_ci}
1554514f5e3Sopenharmony_ci
1564514f5e3Sopenharmony_civoid MemController::StopCalculationAfterGC(TriggerGCType gcType)
1574514f5e3Sopenharmony_ci{
1584514f5e3Sopenharmony_ci    startCounter_--;
1594514f5e3Sopenharmony_ci    if (startCounter_ != 0) {
1604514f5e3Sopenharmony_ci        return;
1614514f5e3Sopenharmony_ci    }
1624514f5e3Sopenharmony_ci
1634514f5e3Sopenharmony_ci    gcEndTime_ = GetSystemTimeInMs();
1644514f5e3Sopenharmony_ci    allocTimeMs_ = gcEndTime_;
1654514f5e3Sopenharmony_ci    if (allocDurationSinceGc_ > 0) {
1664514f5e3Sopenharmony_ci        oldSpaceAllocSizeSinceGC_ += heap_->GetEvacuator()->GetPromotedSize();
1674514f5e3Sopenharmony_ci        recordedEdenSpaceAllocations_.Push(MakeBytesAndDuration(edenSpaceAllocSizeSinceGC_, allocDurationSinceGc_));
1684514f5e3Sopenharmony_ci        recordedNewSpaceAllocations_.Push(MakeBytesAndDuration(newSpaceAllocSizeSinceGC_, allocDurationSinceGc_));
1694514f5e3Sopenharmony_ci        recordedOldSpaceAllocations_.Push(MakeBytesAndDuration(oldSpaceAllocSizeSinceGC_, allocDurationSinceGc_));
1704514f5e3Sopenharmony_ci        recordedNonmovableSpaceAllocations_.Push(
1714514f5e3Sopenharmony_ci            MakeBytesAndDuration(nonMovableSpaceAllocSizeSinceGC_, allocDurationSinceGc_));
1724514f5e3Sopenharmony_ci        recordedCodeSpaceAllocations_.Push(MakeBytesAndDuration(codeSpaceAllocSizeSinceGC_, allocDurationSinceGc_));
1734514f5e3Sopenharmony_ci    }
1744514f5e3Sopenharmony_ci    allocDurationSinceGc_ = 0.0;
1754514f5e3Sopenharmony_ci    edenSpaceAllocSizeSinceGC_ = 0;
1764514f5e3Sopenharmony_ci    newSpaceAllocSizeSinceGC_ = 0;
1774514f5e3Sopenharmony_ci    oldSpaceAllocSizeSinceGC_ = 0;
1784514f5e3Sopenharmony_ci    nonMovableSpaceAllocSizeSinceGC_ = 0;
1794514f5e3Sopenharmony_ci    codeSpaceAllocSizeSinceGC_ = 0;
1804514f5e3Sopenharmony_ci
1814514f5e3Sopenharmony_ci    hugeObjectAllocSizeSinceGC_ = heap_->GetHugeObjectSpace()->GetHeapObjectSize();
1824514f5e3Sopenharmony_ci
1834514f5e3Sopenharmony_ci    double duration = gcEndTime_ - gcStartTime_;
1844514f5e3Sopenharmony_ci    switch (gcType) {
1854514f5e3Sopenharmony_ci        case TriggerGCType::YOUNG_GC:
1864514f5e3Sopenharmony_ci        case TriggerGCType::OLD_GC: {
1874514f5e3Sopenharmony_ci            if (heap_->IsConcurrentFullMark()) {
1884514f5e3Sopenharmony_ci                if (heap_->GetConcurrentMarker()->IsEnabled()) {
1894514f5e3Sopenharmony_ci                    duration += heap_->GetConcurrentMarker()->GetDuration();
1904514f5e3Sopenharmony_ci                }
1914514f5e3Sopenharmony_ci                recordedMarkCompacts_.Push(MakeBytesAndDuration(heap_->GetHeapObjectSize(), duration));
1924514f5e3Sopenharmony_ci            }
1934514f5e3Sopenharmony_ci            break;
1944514f5e3Sopenharmony_ci        }
1954514f5e3Sopenharmony_ci        case TriggerGCType::FULL_GC: {
1964514f5e3Sopenharmony_ci            recordedMarkCompacts_.Push(MakeBytesAndDuration(heap_->GetHeapObjectSize(), duration));
1974514f5e3Sopenharmony_ci            break;
1984514f5e3Sopenharmony_ci        }
1994514f5e3Sopenharmony_ci        default:
2004514f5e3Sopenharmony_ci            break;
2014514f5e3Sopenharmony_ci    }
2024514f5e3Sopenharmony_ci
2034514f5e3Sopenharmony_ci    if (heap_->GetEcmaGCStats()->GetGCReason() != GCReason::IDLE) {
2044514f5e3Sopenharmony_ci        newSpaceRecordLastTimeSizeIdle_ = heap_->GetNewSpace()->GetHeapObjectSize();
2054514f5e3Sopenharmony_ci        oldSpaceRecordLastTimeSizeIdle_ = heap_->GetOldSpace()->GetHeapObjectSize();
2064514f5e3Sopenharmony_ci        allocTimeMsIdle_ = gcEndTime_;
2074514f5e3Sopenharmony_ci    }
2084514f5e3Sopenharmony_ci}
2094514f5e3Sopenharmony_ci
2104514f5e3Sopenharmony_civoid MemController::RecordAfterConcurrentMark(MarkType markType, const ConcurrentMarker *marker)
2114514f5e3Sopenharmony_ci{
2124514f5e3Sopenharmony_ci    double duration = marker->GetDuration();
2134514f5e3Sopenharmony_ci    if (markType == MarkType::MARK_FULL) {
2144514f5e3Sopenharmony_ci        recordedConcurrentMarks_.Push(MakeBytesAndDuration(marker->GetHeapObjectSize(), duration));
2154514f5e3Sopenharmony_ci    } else if (markType == MarkType::MARK_YOUNG) {
2164514f5e3Sopenharmony_ci        recordedSemiConcurrentMarks_.Push(MakeBytesAndDuration(marker->GetHeapObjectSize(), duration));
2174514f5e3Sopenharmony_ci    } else if (markType == MarkType::MARK_EDEN) {
2184514f5e3Sopenharmony_ci        recordedEdenConcurrentMarks_.Push(MakeBytesAndDuration(marker->GetHeapObjectSize(), duration));
2194514f5e3Sopenharmony_ci    }
2204514f5e3Sopenharmony_ci}
2214514f5e3Sopenharmony_ci
2224514f5e3Sopenharmony_cidouble MemController::CalculateMarkCompactSpeedPerMS()
2234514f5e3Sopenharmony_ci{
2244514f5e3Sopenharmony_ci    markCompactSpeedCache_ = CalculateAverageSpeed(recordedMarkCompacts_);
2254514f5e3Sopenharmony_ci    if (markCompactSpeedCache_ > 0) {
2264514f5e3Sopenharmony_ci        return markCompactSpeedCache_;
2274514f5e3Sopenharmony_ci    }
2284514f5e3Sopenharmony_ci    return 0;
2294514f5e3Sopenharmony_ci}
2304514f5e3Sopenharmony_ci
2314514f5e3Sopenharmony_cidouble MemController::CalculateAverageSpeed(const base::GCRingBuffer<BytesAndDuration, LENGTH> &buffer,
2324514f5e3Sopenharmony_ci                                            const BytesAndDuration &initial, const double timeMs)
2334514f5e3Sopenharmony_ci{
2344514f5e3Sopenharmony_ci    BytesAndDuration sum = buffer.Sum(
2354514f5e3Sopenharmony_ci        [timeMs](BytesAndDuration a, BytesAndDuration b) {
2364514f5e3Sopenharmony_ci            if (timeMs != 0 && a.second >= timeMs) {
2374514f5e3Sopenharmony_ci                return a;
2384514f5e3Sopenharmony_ci            }
2394514f5e3Sopenharmony_ci            return std::make_pair(a.first + b.first, a.second + b.second);
2404514f5e3Sopenharmony_ci        },
2414514f5e3Sopenharmony_ci        initial);
2424514f5e3Sopenharmony_ci    uint64_t bytes = sum.first;
2434514f5e3Sopenharmony_ci    double durations = sum.second;
2444514f5e3Sopenharmony_ci    if (fabs(durations) <= 1e-6) {
2454514f5e3Sopenharmony_ci        return 0;
2464514f5e3Sopenharmony_ci    }
2474514f5e3Sopenharmony_ci    double speed = bytes / durations;
2484514f5e3Sopenharmony_ci    const int maxSpeed = static_cast<int>(1_GB);
2494514f5e3Sopenharmony_ci    const int minSpeed = 1;
2504514f5e3Sopenharmony_ci    if (speed >= maxSpeed) {
2514514f5e3Sopenharmony_ci        return maxSpeed;
2524514f5e3Sopenharmony_ci    }
2534514f5e3Sopenharmony_ci    if (speed <= minSpeed) {
2544514f5e3Sopenharmony_ci        return minSpeed;
2554514f5e3Sopenharmony_ci    }
2564514f5e3Sopenharmony_ci    return speed;
2574514f5e3Sopenharmony_ci}
2584514f5e3Sopenharmony_ci
2594514f5e3Sopenharmony_cidouble MemController::CalculateAverageSpeed(const base::GCRingBuffer<BytesAndDuration, LENGTH> &buffer)
2604514f5e3Sopenharmony_ci{
2614514f5e3Sopenharmony_ci    return CalculateAverageSpeed(buffer, MakeBytesAndDuration(0, 0), 0);
2624514f5e3Sopenharmony_ci}
2634514f5e3Sopenharmony_ci
2644514f5e3Sopenharmony_cidouble MemController::GetCurrentOldSpaceAllocationThroughputPerMS(double timeMs) const
2654514f5e3Sopenharmony_ci{
2664514f5e3Sopenharmony_ci    size_t allocatedSize = oldSpaceAllocSizeSinceGC_;
2674514f5e3Sopenharmony_ci    double duration = allocDurationSinceGc_;
2684514f5e3Sopenharmony_ci    return CalculateAverageSpeed(recordedOldSpaceAllocations_,
2694514f5e3Sopenharmony_ci                                 MakeBytesAndDuration(allocatedSize, duration), timeMs);
2704514f5e3Sopenharmony_ci}
2714514f5e3Sopenharmony_ci
2724514f5e3Sopenharmony_cidouble MemController::GetEdenSpaceAllocationThroughputPerMS() const
2734514f5e3Sopenharmony_ci{
2744514f5e3Sopenharmony_ci    return CalculateAverageSpeed(recordedEdenSpaceAllocations_);
2754514f5e3Sopenharmony_ci}
2764514f5e3Sopenharmony_ci
2774514f5e3Sopenharmony_cidouble MemController::GetNewSpaceAllocationThroughputPerMS() const
2784514f5e3Sopenharmony_ci{
2794514f5e3Sopenharmony_ci    return CalculateAverageSpeed(recordedNewSpaceAllocations_);
2804514f5e3Sopenharmony_ci}
2814514f5e3Sopenharmony_ci
2824514f5e3Sopenharmony_cidouble MemController::GetEdenSpaceConcurrentMarkSpeedPerMS() const
2834514f5e3Sopenharmony_ci{
2844514f5e3Sopenharmony_ci    return CalculateAverageSpeed(recordedEdenConcurrentMarks_);
2854514f5e3Sopenharmony_ci}
2864514f5e3Sopenharmony_ci
2874514f5e3Sopenharmony_cidouble MemController::GetNewSpaceConcurrentMarkSpeedPerMS() const
2884514f5e3Sopenharmony_ci{
2894514f5e3Sopenharmony_ci    return CalculateAverageSpeed(recordedSemiConcurrentMarks_);
2904514f5e3Sopenharmony_ci}
2914514f5e3Sopenharmony_ci
2924514f5e3Sopenharmony_cidouble MemController::GetOldSpaceAllocationThroughputPerMS() const
2934514f5e3Sopenharmony_ci{
2944514f5e3Sopenharmony_ci    return CalculateAverageSpeed(recordedOldSpaceAllocations_);
2954514f5e3Sopenharmony_ci}
2964514f5e3Sopenharmony_ci
2974514f5e3Sopenharmony_cidouble MemController::GetFullSpaceConcurrentMarkSpeedPerMS() const
2984514f5e3Sopenharmony_ci{
2994514f5e3Sopenharmony_ci    return CalculateAverageSpeed(recordedConcurrentMarks_);
3004514f5e3Sopenharmony_ci}
3014514f5e3Sopenharmony_ci
3024514f5e3Sopenharmony_cidouble MemController::GetIdleNewSpaceAllocationThroughputPerMS() const
3034514f5e3Sopenharmony_ci{
3044514f5e3Sopenharmony_ci    return CalculateAverageSpeed(recordedIdleNewSpaceAllocations_);
3054514f5e3Sopenharmony_ci}
3064514f5e3Sopenharmony_ci
3074514f5e3Sopenharmony_cidouble MemController::GetIdleOldSpaceAllocationThroughputPerMS() const
3084514f5e3Sopenharmony_ci{
3094514f5e3Sopenharmony_ci    return CalculateAverageSpeed(recordedIdleOldSpaceAllocations_);
3104514f5e3Sopenharmony_ci}
3114514f5e3Sopenharmony_ci
3124514f5e3Sopenharmony_ci}  // namespace panda::ecmascript
313