• 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 #include <algorithm>
16 #include "g1_pause_tracker.h"
17 #include "utils/logger.h"
18 #include "utils/type_converter.h"
19 #include "libpandabase/os/time.h"
20 
21 namespace ark::mem {
G1PauseTracker(int64_t gcPauseIntervalMs,int64_t maxGcTimeMs)22 G1PauseTracker::G1PauseTracker(int64_t gcPauseIntervalMs, int64_t maxGcTimeMs)
23     : gcPauseIntervalUs_(gcPauseIntervalMs * ark::os::time::MILLIS_TO_MICRO),
24       maxGcTimeUs_(maxGcTimeMs * ark::os::time::MILLIS_TO_MICRO)
25 {
26 }
27 
AddPauseInNanos(int64_t startTimeNs,int64_t endTimeNs)28 bool G1PauseTracker::AddPauseInNanos(int64_t startTimeNs, int64_t endTimeNs)
29 {
30     return AddPause(startTimeNs / ark::os::time::MICRO_TO_NANO, endTimeNs / ark::os::time::MICRO_TO_NANO);
31 }
32 
AddPause(int64_t startTimeUs,int64_t endTimeUs)33 bool G1PauseTracker::AddPause(int64_t startTimeUs, int64_t endTimeUs)
34 {
35     RemoveOutOfIntervalEntries(endTimeUs);
36     pauses_.push_back(PauseEntry(startTimeUs, endTimeUs));
37     auto gcTime = CalculateIntervalPauseInMicros(endTimeUs);
38     if (gcTime > maxGcTimeUs_) {
39         LOG(DEBUG, GC) << "Target GC pause was exceeded: "
40                        << ark::helpers::TimeConverter(gcTime * ark::os::time::MICRO_TO_NANO) << " > "
41                        << ark::helpers::TimeConverter(maxGcTimeUs_ * ark::os::time::MICRO_TO_NANO)
42                        << " in time interval "
43                        << ark::helpers::TimeConverter(gcPauseIntervalUs_ * ark::os::time::MICRO_TO_NANO);
44         return false;
45     }
46     return true;
47 }
48 
RemoveOutOfIntervalEntries(int64_t nowUs)49 void G1PauseTracker::RemoveOutOfIntervalEntries(int64_t nowUs)
50 {
51     auto oldestIntervalTime = nowUs - gcPauseIntervalUs_;
52     while (!pauses_.empty()) {
53         auto oldestPause = pauses_.front();
54         if (oldestPause.GetEndTimeInMicros() > oldestIntervalTime) {
55             break;
56         }
57         pauses_.pop_front();
58     }
59 }
60 
CalculateIntervalPauseInMicros(int64_t nowUs)61 int64_t G1PauseTracker::CalculateIntervalPauseInMicros(int64_t nowUs)
62 {
63     int64_t gcTime = 0;
64     auto oldestIntervalTime = nowUs - gcPauseIntervalUs_;
65     auto end = pauses_.cend();
66     for (auto it = pauses_.cbegin(); it != end; ++it) {
67         if (it->GetEndTimeInMicros() > oldestIntervalTime) {
68             gcTime += it->DurationInMicros(oldestIntervalTime);
69         }
70     }
71     return gcTime;
72 }
73 
MinDelayBeforePauseInMicros(int64_t nowUs,int64_t pauseTimeUs)74 int64_t G1PauseTracker::MinDelayBeforePauseInMicros(int64_t nowUs, int64_t pauseTimeUs)
75 {
76     pauseTimeUs = std::min(pauseTimeUs, maxGcTimeUs_);
77     auto gcBudget = maxGcTimeUs_ - pauseTimeUs;
78     auto newIntervalTime = nowUs + pauseTimeUs;
79     auto oldestIntervalTime = newIntervalTime - gcPauseIntervalUs_;
80 
81     auto rend = pauses_.crend();
82     for (auto it = pauses_.crbegin(); it != rend; ++it) {
83         if (it->GetEndTimeInMicros() <= oldestIntervalTime) {
84             break;
85         }
86 
87         auto duration = it->DurationInMicros(oldestIntervalTime);
88         if (duration > gcBudget) {
89             auto newOldestIntervalTime = it->GetEndTimeInMicros() - gcBudget;
90             ASSERT(newOldestIntervalTime >= oldestIntervalTime);
91             return newOldestIntervalTime - oldestIntervalTime;
92         }
93 
94         gcBudget -= duration;
95     }
96 
97     return 0;
98 }
99 
MinDelayBeforeMaxPauseInMicros(int64_t nowUs)100 int64_t G1PauseTracker::MinDelayBeforeMaxPauseInMicros(int64_t nowUs)
101 {
102     return MinDelayBeforePauseInMicros(nowUs, maxGcTimeUs_);
103 }
104 }  // namespace ark::mem
105