• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (c) 2025 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 
16 #include "common_components/heap/allocator/allocator.h"
17 #include "common_components/heap/allocator/region_space.h"
18 #include "common_components/heap/collector/heuristic_gc_policy.h"
19 #include "common_components/heap/heap.h"
20 #include "common_components/tests/test_helper.h"
21 
22 using namespace common;
23 namespace common::test {
24 class HeuristicGCPolicyTest : public common::test::BaseTestWithScope {
25 protected:
SetUpTestCase()26     static void SetUpTestCase()
27     {
28         BaseRuntime::GetInstance()->Init();
29     }
30 
TearDownTestCase()31     static void TearDownTestCase()
32     {
33         BaseRuntime::GetInstance()->Fini();
34     }
35 
SetUp()36     void SetUp() override
37     {
38         holder_ = ThreadHolder::CreateAndRegisterNewThreadHolder(nullptr);
39         scope_ = new ThreadHolder::TryBindMutatorScope(holder_);
40     }
41 
TearDown()42     void TearDown() override
43     {
44         if (scope_ != nullptr) {
45             delete scope_;
46             scope_ = nullptr;
47         }
48     }
49 
50     ThreadHolder *holder_ {nullptr};
51     ThreadHolder::TryBindMutatorScope *scope_ {nullptr};
52 };
53 
HWTEST_F_L0(HeuristicGCPolicyTest,ShouldRestrainGCOnStartupOrSensitive_Test1)54 HWTEST_F_L0(HeuristicGCPolicyTest, ShouldRestrainGCOnStartupOrSensitive_Test1)
55 {
56     HeuristicGCPolicy gcPolicy;
57     gcPolicy.Init();
58     StartupStatusManager::SetStartupStatus(StartupStatus::COLD_STARTUP_FINISH);
59     gcPolicy.TryHeuristicGC();
60     EXPECT_FALSE(gcPolicy.ShouldRestrainGCOnStartupOrSensitive());
61 }
62 
HWTEST_F_L0(HeuristicGCPolicyTest,ShouldRestrainGCOnStartupOrSensitive_Test2)63 HWTEST_F_L0(HeuristicGCPolicyTest, ShouldRestrainGCOnStartupOrSensitive_Test2)
64 {
65     HeuristicGCPolicy gcPolicy;
66     gcPolicy.Init();
67     StartupStatusManager::SetStartupStatus(StartupStatus::COLD_STARTUP);
68     EXPECT_TRUE(gcPolicy.ShouldRestrainGCOnStartupOrSensitive());
69 
70     RegionSpace& theAllocator = reinterpret_cast<RegionSpace&>(Heap::GetHeap().GetAllocator());
71     auto allocated = theAllocator.GetAllocatedBytes();
72     auto param = BaseRuntime::GetInstance()->GetHeapParam();
73     auto size = param.heapSize * KB * HeuristicGCPolicy::COLD_STARTUP_PHASE1_GC_THRESHOLD_RATIO;
74     for (int i = 0; allocated < size; i++) {
75         uintptr_t addr = theAllocator.AllocOldRegion();
76         ASSERT_NE(addr, 0);
77         allocated = theAllocator.GetAllocatedBytes();
78     }
79 
80     StartupStatusManager::SetStartupStatus(StartupStatus::COLD_STARTUP_FINISH);
81     EXPECT_FALSE(gcPolicy.ShouldRestrainGCOnStartupOrSensitive());
82 
83     StartupStatusManager::SetStartupStatus(StartupStatus::COLD_STARTUP);
84     EXPECT_FALSE(gcPolicy.ShouldRestrainGCOnStartupOrSensitive());
85 
86     theAllocator.GetOldSpace().AssembleRecentFull();
87     auto& fromSpace = theAllocator.GetFromSpace();
88     theAllocator.GetOldSpace().AssembleGarbageCandidates(fromSpace);
89     fromSpace.GetFromRegionList().ClearList();
90     allocated = theAllocator.GetAllocatedBytes();
91     EXPECT_EQ(allocated, 0);
92 }
93 
HWTEST_F_L0(HeuristicGCPolicyTest,ShouldRestrainGCOnStartupOrSensitive_Test3)94 HWTEST_F_L0(HeuristicGCPolicyTest, ShouldRestrainGCOnStartupOrSensitive_Test3)
95 {
96     HeuristicGCPolicy gcPolicy;
97     gcPolicy.Init();
98     StartupStatusManager::SetStartupStatus(StartupStatus::COLD_STARTUP_PARTIALLY_FINISH);
99     EXPECT_TRUE(gcPolicy.ShouldRestrainGCOnStartupOrSensitive());
100 
101     RegionSpace& theAllocator = reinterpret_cast<RegionSpace&>(Heap::GetHeap().GetAllocator());
102     auto allocated = theAllocator.GetAllocatedBytes();
103     auto param = BaseRuntime::GetInstance()->GetHeapParam();
104     auto size = param.heapSize * KB * HeuristicGCPolicy::COLD_STARTUP_PHASE2_GC_THRESHOLD_RATIO;
105     for (int i = 0; allocated < size; i++) {
106         uintptr_t addr = theAllocator.AllocOldRegion();
107         ASSERT_NE(addr, 0);
108         allocated = theAllocator.GetAllocatedBytes();
109     }
110 
111     StartupStatusManager::SetStartupStatus(StartupStatus::COLD_STARTUP_FINISH);
112     EXPECT_FALSE(gcPolicy.ShouldRestrainGCOnStartupOrSensitive());
113 
114     StartupStatusManager::SetStartupStatus(StartupStatus::COLD_STARTUP_PARTIALLY_FINISH);
115     EXPECT_FALSE(gcPolicy.ShouldRestrainGCOnStartupOrSensitive());
116 
117     theAllocator.GetOldSpace().AssembleRecentFull();
118     auto& fromSpace = theAllocator.GetFromSpace();
119     theAllocator.GetOldSpace().AssembleGarbageCandidates(fromSpace);
120     fromSpace.GetFromRegionList().ClearList();
121     allocated = theAllocator.GetAllocatedBytes();
122     EXPECT_EQ(allocated, 0);
123 }
124 
HWTEST_F_L0(HeuristicGCPolicyTest,NotifyNativeAllocation)125 HWTEST_F_L0(HeuristicGCPolicyTest, NotifyNativeAllocation)
126 {
127     HeuristicGCPolicy gcPolicy;
128     size_t initialNotified = gcPolicy.GetNotifiedNativeSize();
129     size_t initialObjects = gcPolicy.GetNativeHeapThreshold();
130 
131     gcPolicy.NotifyNativeAllocation(NATIVE_IMMEDIATE_THRESHOLD / 2);
132 
133     EXPECT_EQ(gcPolicy.GetNotifiedNativeSize(), initialNotified + NATIVE_IMMEDIATE_THRESHOLD / 2);
134     EXPECT_NE(gcPolicy.GetNativeHeapThreshold(), initialObjects + 1);
135 }
136 
HWTEST_F_L0(HeuristicGCPolicyTest,NotifyNativeAllocation_TriggerByBytes)137 HWTEST_F_L0(HeuristicGCPolicyTest, NotifyNativeAllocation_TriggerByBytes)
138 {
139     HeuristicGCPolicy gcPolicy;
140     size_t initialNotified = gcPolicy.GetNotifiedNativeSize();
141     size_t initialObjects = gcPolicy.GetNativeHeapThreshold();
142 
143     gcPolicy.NotifyNativeAllocation(NATIVE_IMMEDIATE_THRESHOLD + 1);
144 
145     EXPECT_EQ(gcPolicy.GetNotifiedNativeSize(), initialNotified + NATIVE_IMMEDIATE_THRESHOLD + 1);
146     EXPECT_NE(gcPolicy.GetNativeHeapThreshold(), initialObjects + 1);
147 }
148 
HWTEST_F_L0(HeuristicGCPolicyTest,TryHeuristicGC)149 HWTEST_F_L0(HeuristicGCPolicyTest, TryHeuristicGC)
150 {
151     HeuristicGCPolicy gcPolicy;
152     StartupStatusManager::SetStartupStatus(StartupStatus::COLD_STARTUP_FINISH);
153     Heap::GetHeap().GetCollector().GetGCStats().heapThreshold = 0;
154     gcPolicy.TryHeuristicGC();
155     Heap::GetHeap().GetCollector().GetGCStats().shouldRequestYoung = true;
156     gcPolicy.TryHeuristicGC();
157     EXPECT_EQ(Heap::GetHeap().GetAllocator().GetAllocatedBytes(),
158         Heap::GetHeap().GetCollector().GetGCStats().GetThreshold());
159 }
160 
HWTEST_F_L0(HeuristicGCPolicyTest,ChangeGCParams)161 HWTEST_F_L0(HeuristicGCPolicyTest, ChangeGCParams)
162 {
163     HeuristicGCPolicy gcPolicy;
164     gcPolicy.RecordAliveSizeAfterLastGC(1);
165     gcPolicy.ChangeGCParams(true);
166     EXPECT_EQ(Heap::GetHeap().GetAllocator().GetAllocatedBytes(), 0);
167 }
168 
HWTEST_F_L0(HeuristicGCPolicyTest,CheckAndTriggerHintGC)169 HWTEST_F_L0(HeuristicGCPolicyTest, CheckAndTriggerHintGC)
170 {
171     HeuristicGCPolicy gcPolicy;
172     StartupStatusManager::SetStartupStatus(StartupStatus::COLD_STARTUP);
173     bool result = gcPolicy.CheckAndTriggerHintGC(MemoryReduceDegree::HIGH);
174     ASSERT_FALSE(result);
175 
176     StartupStatusManager::SetStartupStatus(StartupStatus::COLD_STARTUP_FINISH);
177     result = gcPolicy.CheckAndTriggerHintGC(MemoryReduceDegree::HIGH);
178     ASSERT_FALSE(result);
179 
180     gcPolicy.RecordAliveSizeAfterLastGC(1);
181     result = gcPolicy.CheckAndTriggerHintGC(MemoryReduceDegree::HIGH);
182     ASSERT_FALSE(result);
183 
184     result = gcPolicy.CheckAndTriggerHintGC(MemoryReduceDegree::LOW);
185     ASSERT_FALSE(result);
186 }
187 
HWTEST_F_L0(HeuristicGCPolicyTest,NotifyNativeAllocation_TriggerByBytes1)188 HWTEST_F_L0(HeuristicGCPolicyTest, NotifyNativeAllocation_TriggerByBytes1)
189 {
190     HeuristicGCPolicy gcPolicy;
191     size_t initialNotified = gcPolicy.GetNotifiedNativeSize();
192     size_t initialObjects = gcPolicy.GetNativeHeapThreshold();
193 
194     gcPolicy.SetNativeHeapThreshold(1);
195     gcPolicy.NotifyNativeAllocation(NATIVE_IMMEDIATE_THRESHOLD + 1);
196 
197     EXPECT_EQ(gcPolicy.GetNotifiedNativeSize(), initialNotified + NATIVE_IMMEDIATE_THRESHOLD + 1);
198     EXPECT_NE(gcPolicy.GetNativeHeapThreshold(), initialObjects + 1);
199 }
200 } // namespace common::test