1 /** 2 * Copyright (c) 2023-2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 #ifndef PANDA_RUNTIME_MEM_GC_G1_G1_PAUSE_TRACKER_H 16 #define PANDA_RUNTIME_MEM_GC_G1_G1_PAUSE_TRACKER_H 17 18 #include <cstdint> 19 #include <array> 20 #include "libpandabase/macros.h" 21 #include "libpandabase/utils/time.h" 22 #include "libpandabase/utils/ring_buffer.h" 23 24 namespace ark::mem { 25 26 /// Track G1 GC pause goal: pauses sum does not exceed max_gc_time in gc_pause_interval 27 class G1PauseTracker { 28 public: 29 NO_COPY_SEMANTIC(G1PauseTracker); 30 NO_MOVE_SEMANTIC(G1PauseTracker); 31 32 G1PauseTracker(int64_t gcPauseIntervalMs, int64_t maxGcTimeMs); 33 34 ~G1PauseTracker() = default; 35 36 bool AddPauseInNanos(int64_t startTimeNs, int64_t endTimeNs); 37 38 bool AddPause(int64_t startTimeUs, int64_t endTimeUs); 39 40 /// @return minimum delay for pause from now to achieve pause goal 41 int64_t MinDelayBeforePauseInMicros(int64_t nowUs, int64_t pauseTimeUs); 42 43 /// @return minimum delay for maximum allowed pause from now to achieve pause goal 44 int64_t MinDelayBeforeMaxPauseInMicros(int64_t nowUs); 45 46 class Scope { 47 public: ~Scope()48 ~Scope() 49 { 50 owner_->AddPause(startTimeUs_, ark::time::GetCurrentTimeInMicros()); 51 } 52 53 NO_COPY_SEMANTIC(Scope); 54 NO_MOVE_SEMANTIC(Scope); 55 56 private: Scope(G1PauseTracker * owner)57 explicit Scope(G1PauseTracker *owner) : owner_(owner), startTimeUs_(ark::time::GetCurrentTimeInMicros()) {} 58 59 G1PauseTracker *owner_; 60 int64_t startTimeUs_; 61 62 friend class G1PauseTracker; 63 }; 64 CreateScope()65 Scope CreateScope() 66 { 67 return Scope(this); 68 } 69 70 private: 71 class PauseEntry { 72 public: PauseEntry()73 PauseEntry() : PauseEntry(0, 0) {} PauseEntry(int64_t startTimeUs,int64_t endTimeUs)74 PauseEntry(int64_t startTimeUs, int64_t endTimeUs) : startTimeUs_(startTimeUs), endTimeUs_(endTimeUs) 75 { 76 ASSERT(endTimeUs_ >= startTimeUs_); 77 } DurationInMicros()78 int64_t DurationInMicros() const 79 { 80 return endTimeUs_ - startTimeUs_; 81 } DurationInMicros(int64_t oldestIntervalTime)82 int64_t DurationInMicros(int64_t oldestIntervalTime) const 83 { 84 return GetStartTimeInMicros() > oldestIntervalTime ? DurationInMicros() 85 : GetEndTimeInMicros() - oldestIntervalTime; 86 } GetStartTimeInMicros()87 int64_t GetStartTimeInMicros() const 88 { 89 return startTimeUs_; 90 } GetEndTimeInMicros()91 int64_t GetEndTimeInMicros() const 92 { 93 return endTimeUs_; 94 } 95 96 private: 97 int64_t startTimeUs_; 98 int64_t endTimeUs_; 99 }; 100 101 int64_t CalculateIntervalPauseInMicros(int64_t nowUs); 102 void RemoveOutOfIntervalEntries(int64_t nowUs); 103 104 // Need to analyze real apps what size is required 105 static constexpr int SIZE = 16; 106 ark::RingBuffer<PauseEntry, SIZE> pauses_; 107 int64_t gcPauseIntervalUs_; 108 int64_t maxGcTimeUs_; 109 }; 110 } // namespace ark::mem 111 112 #endif // PANDA_RUNTIME_MEM_GC_G1_G1_PAUSE_TRACKER_H 113