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/heap.h"
24 #include "ecmascript/mem/space.h"
25 #include "ecmascript/object_factory.h"
26 #include "ecmascript/tagged_array-inl.h"
27 #include "ecmascript/tests/test_helper.h"
28
29 using namespace panda::ecmascript;
30 using namespace panda::ecmascript::base;
31
32 namespace panda::test {
33 class MemControllerTest : public testing::Test {
34 public:
SetUpTestCase()35 static void SetUpTestCase()
36 {
37 GTEST_LOG_(INFO) << "SetUpTestCase";
38 }
39
TearDownTestCase()40 static void TearDownTestCase()
41 {
42 GTEST_LOG_(INFO) << "TearDownCase";
43 }
44
SetUp()45 void SetUp() override
46 {
47 TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
48 }
49
TearDown()50 void TearDown() override
51 {
52 TestHelper::DestroyEcmaVMWithScope(instance, scope);
53 }
54
55 EcmaVM *instance {nullptr};
56 EcmaHandleScope *scope {nullptr};
57 JSThread *thread {nullptr};
58 };
59
HWTEST_F_L0(MemControllerTest,AllocationVerify)60 HWTEST_F_L0(MemControllerTest, AllocationVerify)
61 {
62 #ifdef NDEBUG
63 auto ecmaVm = thread->GetEcmaVM();
64 auto heap = const_cast<Heap *>(ecmaVm->GetHeap());
65 auto objectFactory = ecmaVm->GetFactory();
66 auto memController = heap->GetMemController();
67
68 heap->CollectGarbage(TriggerGCType::FULL_GC);
69
70 for (int i = 0; i < 1024; i++) {
71 // old space object
72 [[maybe_unused]] auto oldArray = objectFactory->NewTaggedArray(128, JSTaggedValue::Undefined(),
73 MemSpaceType::OLD_SPACE);
74 }
75 sleep(5);
76 heap->CollectGarbage(TriggerGCType::FULL_GC);
77 double mutatorSpeed1 = memController->GetCurrentOldSpaceAllocationThroughputPerMS(0);
78 for (int i = 0; i < 1024; i++) {
79 // old space object
80 [[maybe_unused]] auto oldArray = objectFactory->NewTaggedArray(128, JSTaggedValue::Undefined(),
81 MemSpaceType::OLD_SPACE);
82 }
83 sleep(10);
84
85 heap->CollectGarbage(TriggerGCType::FULL_GC);
86 double mutatorSpeed2 = memController->GetCurrentOldSpaceAllocationThroughputPerMS(0);
87 ASSERT_TRUE(mutatorSpeed2 < mutatorSpeed1);
88 #endif
89 }
90
HWTEST_F_L0(MemControllerTest,VerifyMutatorSpeed)91 HWTEST_F_L0(MemControllerTest, VerifyMutatorSpeed)
92 {
93 #ifdef NDEBUG
94 auto ecmaVm = thread->GetEcmaVM();
95 auto heap = const_cast<Heap *>(ecmaVm->GetHeap());
96 auto objectFactory = ecmaVm->GetFactory();
97 auto memController = heap->GetMemController();
98
99 heap->CollectGarbage(TriggerGCType::YOUNG_GC);
100 size_t oldSpaceAllocatedSizeBefore = memController->GetOldSpaceAllocAccumulatedSize();
101 size_t nonMovableSpaceAllocatedSizeBefore = memController->GetNonMovableSpaceAllocAccumulatedSize();
102 double allocDurationBefore = memController->GetAllocTimeMs();
103 sleep(1);
104
105 // new space object
106 [[maybe_unused]] auto newArray =
107 objectFactory->NewTaggedArray(2, JSTaggedValue::Undefined(), MemSpaceType::SEMI_SPACE);
108 // old space object
109 auto oldArray = objectFactory->NewTaggedArray(2, JSTaggedValue::Undefined(), MemSpaceType::OLD_SPACE);
110 // non movable object
111 auto nonMovableArray = objectFactory->NewTaggedArray(2, JSTaggedValue::Undefined(), MemSpaceType::NON_MOVABLE);
112 // huge space object
113 static constexpr size_t SIZE = 1_MB;
114 auto hugeArray = objectFactory->NewTaggedArray(SIZE);
115
116 auto newSpace = heap->GetNewSpace();
117 size_t newSpaceAllocBytesSinceGC = newSpace->GetAllocatedSizeSinceGC(newSpace->GetTop());
118 ASSERT_EQ(newSpaceAllocBytesSinceGC, TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), 2));
119 heap->CollectGarbage(TriggerGCType::YOUNG_GC);
120 newSpace = heap->GetNewSpace();
121 ASSERT_EQ(newSpace->GetAllocatedSizeSinceGC(newSpace->GetTop()), static_cast<size_t>(0));
122
123 size_t oldSpaceAllocatedSizeAfter = memController->GetOldSpaceAllocAccumulatedSize();
124 size_t nonMovableSpaceAllocatedSizeAfter = memController->GetNonMovableSpaceAllocAccumulatedSize();
125 double allocDurationAfter = memController->GetAllocTimeMs();
126
127 size_t hugeObjectAllocSizeInLastGC = memController->GetHugeObjectAllocSizeSinceGC();
128
129 ASSERT_TRUE(allocDurationAfter - allocDurationBefore > 1000);
130 ASSERT_TRUE(oldSpaceAllocatedSizeAfter - oldSpaceAllocatedSizeBefore
131 == oldArray->ComputeSize(JSTaggedValue::TaggedTypeSize(), 2));
132 ASSERT_TRUE(nonMovableSpaceAllocatedSizeAfter - nonMovableSpaceAllocatedSizeBefore
133 == nonMovableArray->ComputeSize(JSTaggedValue::TaggedTypeSize(), 2));
134 // The allocated size of huge object must be larger than the object size.
135 ASSERT_TRUE(hugeObjectAllocSizeInLastGC > hugeArray->ComputeSize(JSTaggedValue::TaggedTypeSize(), SIZE));
136 #endif
137 }
138 } // namespace panda::test
139