1 /*
2 * Copyright (c) 2021 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 "ecmascript/ecma_string.h"
17 #include "ecmascript/ecma_vm.h"
18 #include "ecmascript/js_hclass.h"
19 #include "ecmascript/js_object-inl.h"
20 #include "ecmascript/js_thread.h"
21
22 #include "ecmascript/mem/mem_common.h"
23 #include "ecmascript/mem/mem_controller_utils.h"
24 #include "ecmascript/mem/heap.h"
25 #include "ecmascript/mem/space.h"
26 #include "ecmascript/object_factory.h"
27 #include "ecmascript/tagged_array-inl.h"
28 #include "ecmascript/tests/test_helper.h"
29
30 using namespace panda::ecmascript;
31 using namespace panda::ecmascript::base;
32
33 namespace panda::test {
34 class MemControllerTest : public BaseTestWithScope<false> {
35 };
36
HWTEST_F_L0(MemControllerTest,AllocationVerify)37 HWTEST_F_L0(MemControllerTest, AllocationVerify)
38 {
39 #ifdef NDEBUG
40 auto ecmaVm = thread->GetEcmaVM();
41 auto heap = const_cast<Heap *>(ecmaVm->GetHeap());
42 auto objectFactory = ecmaVm->GetFactory();
43 auto memController = heap->GetMemController();
44
45 heap->CollectGarbage(TriggerGCType::FULL_GC);
46
47 for (int i = 0; i < 1024; i++) {
48 // old space object
49 [[maybe_unused]] auto oldArray = objectFactory->NewTaggedArray(128, JSTaggedValue::Undefined(),
50 MemSpaceType::OLD_SPACE);
51 }
52 sleep(5);
53 heap->CollectGarbage(TriggerGCType::FULL_GC);
54 double mutatorSpeed1 = memController->GetCurrentOldSpaceAllocationThroughputPerMS(0);
55 for (int i = 0; i < 1024; i++) {
56 // old space object
57 [[maybe_unused]] auto oldArray = objectFactory->NewTaggedArray(128, JSTaggedValue::Undefined(),
58 MemSpaceType::OLD_SPACE);
59 }
60 sleep(10);
61
62 heap->CollectGarbage(TriggerGCType::FULL_GC);
63 double mutatorSpeed2 = memController->GetCurrentOldSpaceAllocationThroughputPerMS(0);
64 ASSERT_TRUE(mutatorSpeed2 < mutatorSpeed1);
65 #endif
66 }
67
HWTEST_F_L0(MemControllerTest,VerifyMutatorSpeed)68 HWTEST_F_L0(MemControllerTest, VerifyMutatorSpeed)
69 {
70 #ifdef NDEBUG
71 auto ecmaVm = thread->GetEcmaVM();
72 auto heap = const_cast<Heap *>(ecmaVm->GetHeap());
73 auto objectFactory = ecmaVm->GetFactory();
74 auto memController = heap->GetMemController();
75
76 heap->CollectGarbage(TriggerGCType::YOUNG_GC);
77 size_t oldSpaceAllocatedSizeBefore = memController->GetOldSpaceAllocAccumulatedSize();
78 size_t nonMovableSpaceAllocatedSizeBefore = memController->GetNonMovableSpaceAllocAccumulatedSize();
79 double allocDurationBefore = memController->GetAllocTimeMs();
80 sleep(1);
81
82 // new space object
83 [[maybe_unused]] auto newArray =
84 objectFactory->NewTaggedArray(2, JSTaggedValue::Undefined(), MemSpaceType::SEMI_SPACE);
85 // old space object
86 auto oldArray = objectFactory->NewTaggedArray(2, JSTaggedValue::Undefined(), MemSpaceType::OLD_SPACE);
87 // non movable object
88 auto nonMovableArray = objectFactory->NewTaggedArray(2, JSTaggedValue::Undefined(), MemSpaceType::NON_MOVABLE);
89 // huge space object
90 static constexpr size_t SIZE = 1_MB;
91 auto hugeArray = objectFactory->NewTaggedArray(SIZE);
92
93 auto newSpace = heap->GetNewSpace();
94 size_t newSpaceAllocBytesSinceGC = newSpace->GetAllocatedSizeSinceGC(newSpace->GetTop());
95 ASSERT_EQ(newSpaceAllocBytesSinceGC, TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), 2));
96 heap->CollectGarbage(TriggerGCType::YOUNG_GC);
97 newSpace = heap->GetNewSpace();
98 ASSERT_EQ(newSpace->GetAllocatedSizeSinceGC(newSpace->GetTop()), static_cast<size_t>(0));
99
100 size_t oldSpaceAllocatedSizeAfter = memController->GetOldSpaceAllocAccumulatedSize();
101 size_t nonMovableSpaceAllocatedSizeAfter = memController->GetNonMovableSpaceAllocAccumulatedSize();
102 double allocDurationAfter = memController->GetAllocTimeMs();
103
104 size_t hugeObjectAllocSizeInLastGC = memController->GetHugeObjectAllocSizeSinceGC();
105
106 ASSERT_TRUE(allocDurationAfter - allocDurationBefore > 1000);
107 ASSERT_TRUE(oldSpaceAllocatedSizeAfter - oldSpaceAllocatedSizeBefore
108 == oldArray->ComputeSize(JSTaggedValue::TaggedTypeSize(), 2));
109 ASSERT_TRUE(nonMovableSpaceAllocatedSizeAfter - nonMovableSpaceAllocatedSizeBefore
110 == nonMovableArray->ComputeSize(JSTaggedValue::TaggedTypeSize(), 2));
111 // The allocated size of huge object must be larger than the object size.
112 ASSERT_TRUE(hugeObjectAllocSizeInLastGC > hugeArray->ComputeSize(JSTaggedValue::TaggedTypeSize(), SIZE));
113 #endif
114 }
115
HWTEST_F_L0(MemControllerTest,CalculateMarkCompactSpeedPerMSTest)116 HWTEST_F_L0(MemControllerTest, CalculateMarkCompactSpeedPerMSTest)
117 {
118 #ifdef NDEBUG
119 auto ecmaVm = thread->GetEcmaVM();
120 auto heap = const_cast<Heap *>(ecmaVm->GetHeap());
121 auto memController = heap->GetMemController();
122 auto compactSpeed = memController->CalculateMarkCompactSpeedPerMS();
123 EXPECT_TRUE(compactSpeed == 0);
124 #endif
125 }
126
HWTEST_F_L0(MemControllerTest,StartCalculationBeforeGC)127 HWTEST_F_L0(MemControllerTest, StartCalculationBeforeGC)
128 {
129 JSNApi::InitHybridVMEnv(thread->GetEcmaVM());
130 auto ecmaVm = thread->GetEcmaVM();
131 auto heap = const_cast<Heap *>(ecmaVm->GetHeap());
132 auto memController = heap->GetMemController();
133 auto objectFactory = ecmaVm->GetFactory();
134
135 // huge space object
136 static constexpr size_t SIZE = 1_MB;
137 objectFactory->NewTaggedArray(SIZE);
138
139 double allocTimeMsBefore = memController->GetAllocTimeMs();
140 size_t oldSpaceSizeBefore = memController->GetOldSpaceAllocAccumulatedSize();
141 size_t nonMovableSpaceSizeBefore = memController->GetNonMovableSpaceAllocAccumulatedSize();
142 size_t codeSpaceSizeBefore = memController->GetCodeSpaceAllocAccumulatedSize();
143 {
144 [[maybe_unused]] auto newArray =
145 objectFactory->NewTaggedArray(20, JSTaggedValue::Undefined(), MemSpaceType::SEMI_SPACE);
146 // old space object
147 [[maybe_unused]] auto oldArray =
148 objectFactory->NewTaggedArray(20, JSTaggedValue::Undefined(), MemSpaceType::OLD_SPACE);
149 // non movable object
150 [[maybe_unused]] auto nonMovableArray =
151 objectFactory->NewTaggedArray(20, JSTaggedValue::Undefined(), MemSpaceType::NON_MOVABLE);
152 }
153
154 sleep(1);
155 heap->CollectGarbage(TriggerGCType::FULL_GC);
156 memController->StartCalculationBeforeGC();
157 memController->CheckLowAllocationUsageState();
158
159 double allocTimeMsAfter = memController->GetAllocTimeMs();
160 size_t oldSpaceSizeAfter = memController->GetOldSpaceAllocAccumulatedSize();
161 size_t nonMovableSpaceSizeAfter = memController->GetNonMovableSpaceAllocAccumulatedSize();
162 size_t codeSpaceSizeAfter = memController->GetCodeSpaceAllocAccumulatedSize();
163
164 EXPECT_TRUE(allocTimeMsAfter - allocTimeMsBefore > 1000);
165 EXPECT_TRUE(oldSpaceSizeAfter > oldSpaceSizeBefore);
166 EXPECT_TRUE(nonMovableSpaceSizeAfter > nonMovableSpaceSizeBefore);
167 EXPECT_TRUE(codeSpaceSizeAfter == codeSpaceSizeBefore);
168 }
169
HWTEST_F_L0(MemControllerTest,StopCalculationAfterGC)170 HWTEST_F_L0(MemControllerTest, StopCalculationAfterGC)
171 {
172 auto ecmaVm = thread->GetEcmaVM();
173 auto heap = const_cast<Heap *>(ecmaVm->GetHeap());
174 auto objectFactory = ecmaVm->GetFactory();
175 auto memController = heap->GetMemController();
176 heap->CollectGarbage(TriggerGCType::FULL_GC);
177
178 [[maybe_unused]] auto newArray =
179 objectFactory->NewTaggedArray(2, JSTaggedValue::Undefined(), MemSpaceType::SEMI_SPACE);
180 [[maybe_unused]] auto oldArray =
181 objectFactory->NewTaggedArray(2, JSTaggedValue::Undefined(), MemSpaceType::OLD_SPACE);
182 [[maybe_unused]] auto nonMovableArray =
183 objectFactory->NewTaggedArray(2, JSTaggedValue::Undefined(), MemSpaceType::NON_MOVABLE);
184 static constexpr size_t SIZE = 1_MB;
185 [[maybe_unused]] auto hugeArray = objectFactory->NewTaggedArray(SIZE);
186
187 heap->CollectGarbage(TriggerGCType::YOUNG_GC);
188
189 double allocDurationSinceGc = memController->GetAllocDurationSinceGc();
190 size_t codeSpaceAllocSizeSinceGC = memController->GetCodeSpaceAllocAccumulatedSize();
191 EXPECT_EQ(allocDurationSinceGc, static_cast<double>(0.0));
192 EXPECT_EQ(codeSpaceAllocSizeSinceGC, static_cast<size_t>(0));
193 size_t hugeObjectSize = heap->GetHugeObjectSpace()->GetHeapObjectSize();
194 size_t hugeAllocSizeSinceGC = memController->GetHugeObjectAllocSizeSinceGC();
195 EXPECT_EQ(hugeAllocSizeSinceGC, hugeObjectSize);
196 double markCompactSpeed = memController->CalculateMarkCompactSpeedPerMS();
197 EXPECT_GE(markCompactSpeed, 0);
198 }
199
HWTEST_F_L0(MemControllerTest,MemControllerUtilsTest001)200 HWTEST_F_L0(MemControllerTest, MemControllerUtilsTest001)
201 {
202 base::GCRingBuffer<BytesAndDuration, 10> buffer;
203 BytesAndDuration initial = {1_GB + 1, 1};
204 double timeMs = 1;
205 double result = MemControllerUtils::CalculateAverageSpeed(buffer, initial, timeMs);
206 EXPECT_GE(result, 1_GB);
207 }
208
HWTEST_F_L0(MemControllerTest,MemControllerUtilsTest002)209 HWTEST_F_L0(MemControllerTest, MemControllerUtilsTest002)
210 {
211 base::GCRingBuffer<BytesAndDuration, 10> buffer;
212 BytesAndDuration initial = {0, 0};
213 double timeMs = 0;
214 double result = MemControllerUtils::CalculateAverageSpeed(buffer, initial, timeMs);
215 EXPECT_GE(result, 0);
216 }
217
HWTEST_F_L0(MemControllerTest,MemControllerUtilsTest003)218 HWTEST_F_L0(MemControllerTest, MemControllerUtilsTest003)
219 {
220 base::GCRingBuffer<BytesAndDuration, 10> buffer;
221 BytesAndDuration initial = {1, 1_GB + 1};
222 double timeMs = 1;
223 double result = MemControllerUtils::CalculateAverageSpeed(buffer, initial, timeMs);
224 EXPECT_GE(result, 1);
225 }
226
HWTEST_F_L0(MemControllerTest,MemControllerUtilsTest004)227 HWTEST_F_L0(MemControllerTest, MemControllerUtilsTest004)
228 {
229 base::GCRingBuffer<BytesAndDuration, 10> buffer;
230 BytesAndDuration initial = {1_GB / 2, 1};
231 double timeMs = 1;
232 double result = MemControllerUtils::CalculateAverageSpeed(buffer, initial, timeMs);
233 EXPECT_GE(result, 1_GB / 2);
234 }
235
HWTEST_F_L0(MemControllerTest,MemControllerUtilsTest005)236 HWTEST_F_L0(MemControllerTest, MemControllerUtilsTest005)
237 {
238 base::GCRingBuffer<BytesAndDuration, 10> buffer;
239 double result = MemControllerUtils::CalculateAverageSpeed(buffer);
240 EXPECT_GE(result, 0);
241 }
242
243 } // namespace panda::test
244