/* * Copyright (c) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ECMASCRIPT_MEM_MEM_CONTROLLER_H #define ECMASCRIPT_MEM_MEM_CONTROLLER_H #include #include "ecmascript/base/gc_ring_buffer.h" #include "ecmascript/mem/heap.h" #include "ecmascript/mem/mem.h" namespace panda::ecmascript { constexpr static int MILLISECONDS_PER_SECOND = 1000; using BytesAndDuration = std::pair; inline BytesAndDuration MakeBytesAndDuration(uint64_t bytes, double duration) { return std::make_pair(bytes, duration); } class MemController { public: explicit MemController(Heap* heap); MemController() = default; ~MemController() = default; NO_COPY_SEMANTIC(MemController); NO_MOVE_SEMANTIC(MemController); static double GetSystemTimeInMs() { double currentTime = std::chrono::duration(std::chrono::high_resolution_clock::now().time_since_epoch()).count(); return currentTime * MILLISECOND_PER_SECOND; } size_t CalculateAllocLimit(size_t currentSize, size_t minSize, size_t maxSize, size_t newSpaceCapacity, double factor) const; double CalculateGrowingFactor(double gcSpeed, double mutatorSpeed); void StartCalculationBeforeGC(); void StopCalculationAfterGC(TriggerGCType gcType); void RecordAfterConcurrentMark(const bool isFull, const ConcurrentMarker *marker); double CalculateMarkCompactSpeedPerMS(); double GetCurrentOldSpaceAllocationThroughputPerMS(double timeMs = THROUGHPUT_TIME_FRAME_MS) const; double GetNewSpaceAllocationThroughputPerMS() const; double GetOldSpaceAllocationThroughputPerMS() const; double GetNewSpaceConcurrentMarkSpeedPerMS() const; double GetFullSpaceConcurrentMarkSpeedPerMS() const; double GetAllocTimeMs() const { return allocTimeMs_; } size_t GetOldSpaceAllocAccumulatedSize() const { return oldSpaceAllocAccumulatedSize_; } size_t GetNonMovableSpaceAllocAccumulatedSize() const { return nonMovableSpaceAllocAccumulatedSize_; } size_t GetCodeSpaceAllocAccumulatedSize() const { return codeSpaceAllocAccumulatedSize_; } double GetAllocDurationSinceGc() const { return allocDurationSinceGc_; } size_t GetNewSpaceAllocSizeSinceGC() const { return newSpaceAllocSizeSinceGC_; } size_t GetOldSpaceAllocSizeSinceGC() const { return oldSpaceAllocSizeSinceGC_; } size_t GetNonMovableSpaceAllocSizeSinceGC() const { return nonMovableSpaceAllocSizeSinceGC_; } size_t GetCodeSpaceAllocSizeSinceGC() const { return codeSpaceAllocSizeSinceGC_; } size_t GetHugeObjectAllocSizeSinceGC() const { return hugeObjectAllocSizeSinceGC_; } void AddSurvivalRate(double rate) { recordedSurvivalRates_.Push(rate); } double GetAverageSurvivalRate() const { int count = recordedSurvivalRates_.Count(); if (count == 0) { return 0; } double result = recordedSurvivalRates_.Sum([](double x, double y) { return x + y;}, 0.0); return result / count; } void ResetRecordedSurvivalRates() { recordedSurvivalRates_.Reset(); } private: static constexpr int LENGTH = 10; static double CalculateAverageSpeed(const base::GCRingBuffer &buffer); static double CalculateAverageSpeed(const base::GCRingBuffer &buffer, const BytesAndDuration &initial, const double timeMs); Heap* heap_; size_t minAllocLimitGrowingStep_ {0}; double gcStartTime_ {0.0}; double gcEndTime_ {0.0}; // Time and allocation accumulators. double allocTimeMs_ {0.0}; size_t oldSpaceAllocAccumulatedSize_ {0}; size_t nonMovableSpaceAllocAccumulatedSize_ {0}; size_t codeSpaceAllocAccumulatedSize_ {0}; // Duration and allocation size in last gc. double allocDurationSinceGc_ {0.0}; size_t newSpaceAllocSizeSinceGC_ {0}; size_t oldSpaceAllocSizeSinceGC_ {0}; size_t nonMovableSpaceAllocSizeSinceGC_ {0}; size_t codeSpaceAllocSizeSinceGC_ {0}; size_t hugeObjectAllocSizeSinceGC_{0}; int startCounter_ {0}; double markCompactSpeedCache_ {0.0}; base::GCRingBuffer recordedMarkCompacts_; base::GCRingBuffer recordedNewSpaceAllocations_; base::GCRingBuffer recordedOldSpaceAllocations_; base::GCRingBuffer recordedNonmovableSpaceAllocations_; base::GCRingBuffer recordedCodeSpaceAllocations_; base::GCRingBuffer recordedConcurrentMarks_; base::GCRingBuffer recordedSemiConcurrentMarks_; base::GCRingBuffer recordedSurvivalRates_; static constexpr double THROUGHPUT_TIME_FRAME_MS = 5000; static constexpr int MILLISECOND_PER_SECOND = 1000; }; MemController *CreateMemController(Heap *heap, std::string_view gcTriggerType); } // namespace panda::ecmascript #endif // ECMASCRIPT_MEM_MEM_CONTROLLER_H