• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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