* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <chrono>
#include <thread>
#include "ecmascript/builtins/builtins_ark_tools.h"
#include "ecmascript/ecma_vm.h"
#include "ecmascript/mem/full_gc.h"
#include "ecmascript/mem/idle_gc_trigger.h"
#include "ecmascript/object_factory-inl.h"
#include "ecmascript/mem/concurrent_marker.h"
#include "ecmascript/mem/partial_gc.h"
#include "ecmascript/tests/ecma_test_common.h"
#include "ecmascript/napi/include/jsnapi_expo.h"
#include "ecmascript/mem/free_object_list.h"
#include "ecmascript/mem/gc_stats.h"
#include "ecmascript/mem/free_object_set.h"
#include "ecmascript/mem/shared_mem_controller.h"
#include "ecmascript/mem/mem_controller_utils.h"
#include "ecmascript/mem/mem_controller.h"
#if defined(PANDA_TARGET_OHOS) && !defined(STANDALONE_MODE)
#include "parameters.h"
#endif
using namespace panda;
using namespace panda::ecmascript;
using TRIGGER_IDLE_GC_TYPE = panda::JSNApi::TRIGGER_IDLE_GC_TYPE;
namespace panda::test {
class GCTest : public BaseTestWithScope<false> {
public:
void SetUp() override
{
#if defined(PANDA_TARGET_OHOS) && !defined(STANDALONE_MODE)
OHOS::system::SetParameter("persist.ark.sheap.growfactor", "10");
OHOS::system::SetParameter("persist.ark.sheap.growstep", "640");
OHOS::system::SetParameter("persist.ark.sensitive.threshold", "640");
OHOS::system::SetParameter("persist.ark.native.stepsize", "2048");
OHOS::system::SetParameter("persist.ark.global.alloclimit", "256");
#endif
JSRuntimeOptions options;
instance = JSNApi::CreateEcmaVM(options);
ASSERT_TRUE(instance != nullptr) << "Cannot create EcmaVM";
thread = instance->GetJSThread();
thread->ManagedCodeBegin();
scope = new EcmaHandleScope(thread);
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
heap->GetConcurrentMarker()->EnableConcurrentMarking(EnableConcurrentMarkType::ENABLE);
heap->GetSweeper()->EnableConcurrentSweep(EnableConcurrentSweepType::ENABLE);
}
};
class TestableGCStats : public GCStats {
public:
explicit TestableGCStats(const Heap *heap) : GCStats(heap) {}
using GCStats::GetGCStatistic;
using GCStats::GetGCStatisticType;
using GCStats::MergeGCStatistic;
using GCStats::RecordGCStatisticEnd;
using GCStats::RecordGCStatisticStart;
using GCStats::SetRecordDuration;
void SetGCTypeForTest(GCType type)
{
gcType_ = type;
}
};
HWTEST_F_L0(GCTest, NativeGCTestConcurrentMarkDisabled)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
heap->GetConcurrentMarker()->ConfigConcurrentMark(false);
size_t oldNativeSize = heap->GetNativeBindingSize();
EcmaTestCommon::GcCommonCase(thread, heap, false);
const_cast<Heap *>(thread->GetEcmaVM()->GetHeap())->CollectGarbage(TriggerGCType::OLD_GC);
auto newNativeSize = heap->GetNativeBindingSize();
EXPECT_EQ(newNativeSize - oldNativeSize, 0UL);
}
HWTEST_F_L0(GCTest, NonNewSpaceNativeGCTestConcurrentMarkDisabled)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
heap->GetConcurrentMarker()->ConfigConcurrentMark(false);
size_t oldNativeSize = heap->GetNativeBindingSize();
EcmaTestCommon::GcCommonCase(thread, heap);
const_cast<Heap *>(thread->GetEcmaVM()->GetHeap())->CollectGarbage(TriggerGCType::OLD_GC);
auto newNativeSize = heap->GetNativeBindingSize();
EXPECT_EQ(newNativeSize - oldNativeSize, 0UL);
}
HWTEST_F_L0(GCTest, CSetTest)
{
ObjectFactory *factory = instance->GetFactory();
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
constexpr uint32_t length = 300;
heap->SetSensitiveStatus(AppSensitiveStatus::ENTER_HIGH_SENSITIVE);
JSHandle<TaggedArray> array = factory->NewTaggedArray(length, JSTaggedValue::Undefined());
instance->CollectGarbage(TriggerGCType::OLD_GC, GCReason::ALLOCATION_FAILED);
instance->CollectGarbage(TriggerGCType::OLD_GC);
Region *region = Region::ObjectAddressToRange(*array);
heap->SetFullMarkRequestedState(true);
heap->TryTriggerConcurrentMarking(MarkReason::OTHER);
EXPECT_TRUE(!region->InCollectSet());
}
HWTEST_F_L0(GCTest, ArkToolsForceFullGC)
{
const_cast<Heap *>(thread->GetEcmaVM()->GetHeap())->CollectGarbage(TriggerGCType::FULL_GC);
size_t originalHeapSize = thread->GetEcmaVM()->GetHeap()->GetCommittedSize();
size_t newSize = originalHeapSize;
{
[[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread);
for (int i = 0; i < 10; i++) {
[[maybe_unused]] JSHandle<TaggedArray> obj = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(1024 * 1024);
}
newSize = thread->GetEcmaVM()->GetHeap()->GetCommittedSize();
}
EXPECT_TRUE(newSize > originalHeapSize);
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 0);
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
[[maybe_unused]] JSTaggedValue result1 = builtins::BuiltinsArkTools::ForceFullGC(ecmaRuntimeCallInfo);
ASSERT_TRUE(thread->GetEcmaVM()->GetHeap()->GetCommittedSize() < newSize);
}
HWTEST_F_L0(GCTest, ColdStartForceExpand)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
size_t originalHeapSize = heap->GetCommittedSize();
heap->GetConcurrentMarker()->ConfigConcurrentMark(false);
heap->NotifyPostFork();
heap->NotifyFinishColdStartSoon();
{
[[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread);
for (int i = 0; i < 500; i++) {
[[maybe_unused]] JSHandle<TaggedArray> array = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(
10 * 1024, JSTaggedValue::Hole(), MemSpaceType::SEMI_SPACE);
}
}
size_t expandHeapSize = thread->GetEcmaVM()->GetHeap()->GetCommittedSize();
usleep(10000000);
size_t newSize = EcmaTestCommon::GcCommonCase(thread);
EXPECT_TRUE(originalHeapSize < expandHeapSize);
if constexpr (G_USE_CMS_GC) {
return;
}
EXPECT_TRUE(expandHeapSize > newSize);
}
HWTEST_F_L0(GCTest, HighSensitiveForceExpand)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
size_t originalHeapSize = heap->GetCommittedSize();
heap->GetConcurrentMarker()->ConfigConcurrentMark(false);
heap->NotifyHighSensitive(true);
{
[[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread);
for (int i = 0; i < 500; i++) {
[[maybe_unused]] JSHandle<TaggedArray> array = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(
10 * 1024, JSTaggedValue::Hole(), MemSpaceType::SEMI_SPACE);
}
}
size_t expandHeapSize = thread->GetEcmaVM()->GetHeap()->GetCommittedSize();
const_cast<Heap *>(thread->GetEcmaVM()->GetHeap())->NotifyHighSensitive(false);
size_t newSize = EcmaTestCommon::GcCommonCase(thread);
EXPECT_TRUE(originalHeapSize < expandHeapSize);
if constexpr (G_USE_CMS_GC) {
return;
}
EXPECT_TRUE(expandHeapSize > newSize);
}
HWTEST_F_L0(GCTest, HighSensitiveExceedMaxHeapSize)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
heap->NotifyHighSensitive(true);
{
[[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread);
for (int i = 0; i < 16 * 1000; i++) {
[[maybe_unused]] JSHandle<TaggedArray> array = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(
1024, JSTaggedValue::Hole(), MemSpaceType::SEMI_SPACE);
}
}
{
[[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread);
for (int i = 0; i < 10 * 1000; i++) {
[[maybe_unused]] JSHandle<TaggedArray> array = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(
1024, JSTaggedValue::Hole(), MemSpaceType::SEMI_SPACE);
}
}
size_t commitSize = thread->GetEcmaVM()->GetHeap()->GetCommittedSize();
const_cast<Heap *>(thread->GetEcmaVM()->GetHeap())->NotifyHighSensitive(false);
EXPECT_TRUE(commitSize < thread->GetEcmaVM()->GetEcmaParamConfiguration().GetMaxHeapSize());
}
HWTEST_F_L0(GCTest, HighSensitiveExceedMaxHeapSizeVerify)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
heap->Prepare();
heap->EnableHeapVerication(true);
heap->NotifyHighSensitive(true);
{
[[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread);
for (int i = 0; i < 16 * 1000; i++) {
[[maybe_unused]] JSHandle<TaggedArray> array = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(
1024, JSTaggedValue::Hole(), MemSpaceType::SEMI_SPACE);
}
}
{
[[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread);
for (int i = 0; i < 10 * 1000; i++) {
[[maybe_unused]] JSHandle<TaggedArray> array = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(
1024, JSTaggedValue::Hole(), MemSpaceType::SEMI_SPACE);
}
}
size_t commitSize = thread->GetEcmaVM()->GetHeap()->GetCommittedSize();
const_cast<Heap *>(thread->GetEcmaVM()->GetHeap())->NotifyHighSensitive(false);
EXPECT_TRUE(commitSize < thread->GetEcmaVM()->GetEcmaParamConfiguration().GetMaxHeapSize());
}
HWTEST_F_L0(GCTest, HighSensitiveExceedMaxHeapSizeSyncSweepVerify)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
heap->Prepare();
heap->GetSweeper()->EnableConcurrentSweep(EnableConcurrentSweepType::DISABLE);
heap->EnableHeapVerication(true);
heap->NotifyHighSensitive(true);
{
[[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread);
for (int i = 0; i < 16 * 1000; i++) {
[[maybe_unused]] JSHandle<TaggedArray> array = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(
1024, JSTaggedValue::Hole(), MemSpaceType::SEMI_SPACE);
}
}
{
[[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread);
for (int i = 0; i < 10 * 1000; i++) {
[[maybe_unused]] JSHandle<TaggedArray> array = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(
1024, JSTaggedValue::Hole(), MemSpaceType::SEMI_SPACE);
}
}
size_t commitSize = thread->GetEcmaVM()->GetHeap()->GetCommittedSize();
const_cast<Heap *>(thread->GetEcmaVM()->GetHeap())->NotifyHighSensitive(false);
EXPECT_TRUE(commitSize < thread->GetEcmaVM()->GetEcmaParamConfiguration().GetMaxHeapSize());
}
HWTEST_F_L0(GCTest, ColdStartNoConcurrentMark)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
heap->NotifyPostFork();
heap->NotifyHighSensitive(true);
{
[[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread);
for (int i = 0; i < 500; i++) {
[[maybe_unused]] JSHandle<TaggedArray> array = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(
10 * 1024, JSTaggedValue::Hole(), MemSpaceType::SEMI_SPACE);
}
}
EXPECT_FALSE(heap->HandleExitHighSensitiveEvent());
heap->NotifyHighSensitive(false);
EXPECT_FALSE(heap->HandleExitHighSensitiveEvent());
heap->FinishStartupEvent();
heap->NotifyHighSensitive(true);
heap->NotifyHighSensitive(false);
heap->HandleExitHighSensitiveEvent();
heap->NotifyHighSensitive(true);
EXPECT_FALSE(heap->HandleExitHighSensitiveEvent());
}
HWTEST_F_L0(GCTest, ColdStartGCRestrainInternal)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
heap->NotifyPostFork();
heap->NotifyFinishColdStartSoon();
std::this_thread::sleep_for(std::chrono::seconds(3));
if (!heap->OnStartupEvent()) {
StartupStatus startupStatus = heap->GetStartupStatus();
EXPECT_TRUE(startupStatus == StartupStatus::JUST_FINISH_STARTUP);
}
}
HWTEST_F_L0(GCTest, ColdStartGCRestrainExternal)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
heap->NotifyPostFork();
heap->NotifyFinishColdStartSoon();
std::this_thread::sleep_for(std::chrono::seconds(1));
heap->NotifyFinishColdStart(true);
EXPECT_FALSE(heap->OnStartupEvent());
StartupStatus startupStatus = heap->GetStartupStatus();
EXPECT_TRUE(startupStatus == StartupStatus::JUST_FINISH_STARTUP);
}
HWTEST_F_L0(GCTest, ColdStartGCRestrainInGC)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
heap->NotifyPostFork();
heap->NotifyFinishColdStartSoon();
EXPECT_FALSE(heap->InGC());
heap->SetGCState(true);
std::this_thread::sleep_for(std::chrono::seconds(3));
heap->SetGCState(false);
}
HWTEST_F_L0(GCTest, CallbackTask)
{
auto vm = thread->GetEcmaVM();
Heap *heap = const_cast<Heap *>(vm->GetHeap());
auto factory = vm->GetFactory();
{
[[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread);
for (int i = 0; i < 10; i++) {
void *externalPointer = malloc(10);
[[maybe_unused]] JSHandle<JSNativePointer> nativePointer = factory->NewJSNativePointer(
externalPointer, []([[maybe_unused]] void *env, void* pointer, [[maybe_unused]] void* data) {
if (pointer != nullptr) {
free(pointer);
}
},
nullptr, false, 10, Concurrent::YES);
}
}
size_t number = heap->concurrentNativePointerList_.size();
EXPECT_TRUE(number > 0);
heap->CollectGarbage(TriggerGCType::OLD_GC);
size_t newNumber = heap->concurrentNativePointerList_.size();
EXPECT_TRUE(number > newNumber);
}
HWTEST_F_L0(GCTest, RecomputeLimitsTest)
{
if constexpr (G_USE_CMS_GC) {
return;
}
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
auto oldCapacity = heap->GetOldSpace()->GetInitialCapacity();
heap->CollectGarbage(TriggerGCType::FULL_GC);
EXPECT_FALSE(heap->IsConcurrentFullMark());
EXPECT_FALSE(heap->IsFullMarkRequested());
auto newCapacity = heap->GetOldSpace()->GetInitialCapacity();
EXPECT_NE(newCapacity, oldCapacity);
double gcSpeed = heap->GetMemController()->CalculateMarkCompactSpeedPerMS();
double mutatorSpeed = heap->GetMemController()->GetCurrentOldSpaceAllocationThroughputPerMS();
size_t oldSpaceSize = heap->GetOldSpace()->GetHeapObjectSize() + heap->GetHugeObjectSpace()->GetHeapObjectSize() +
heap->GetHugeMachineCodeSpace()->GetHeapObjectSize();
size_t newSpaceCapacity = heap->GetNewSpace()->GetInitialCapacity();
double growingFactor = heap->GetMemController()->CalculateGrowingFactor(gcSpeed, mutatorSpeed);
size_t maxOldSpaceCapacity = heap->GetOldSpace()->GetMaximumCapacity() - newSpaceCapacity;
auto newOldSpaceLimit = heap->GetMemController()->CalculateAllocLimit(oldSpaceSize, MIN_OLD_SPACE_LIMIT,
maxOldSpaceCapacity, newSpaceCapacity, growingFactor);
EXPECT_EQ(newCapacity, newOldSpaceLimit);
}
HWTEST_F_L0(GCTest, GlobalNativeSizeLargerThanLimitTest)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
auto ret = heap->GlobalNativeSizeLargerThanLimit();
EXPECT_FALSE(ret);
heap->GetNativeAreaAllocator()->IncreaseNativeMemoryUsage(300*1000*1000);
ret = heap->GlobalNativeSizeLargerThanLimit();
EXPECT_TRUE(ret);
}
#ifdef NDEBUG
HWTEST_F_L0(GCTest, IdleGCTriggerTest)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
auto idleGCTrigger = heap->GetIdleGCTrigger();
auto sHeap = SharedHeap::GetInstance();
heap->CollectGarbage(TriggerGCType::FULL_GC);
int baseLocalGCCount = heap->GetEcmaGCStats()->GetGCCount();
int baseSharedGCCount = sHeap->GetEcmaGCStats()->GetGCCount();
heap->GetConcurrentMarker()->ConfigConcurrentMark(false);
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
for (int i = 0; i < 5120; i++) {
factory->NewTaggedArray(1024, JSTaggedValue::Hole(), MemSpaceType::OLD_SPACE);
factory->NewSOldSpaceTaggedArray(1024, JSTaggedValue::Hole());
}
for (size_t i = 0; i < 10240; i++)
{
factory->NewTaggedArray(512, JSTaggedValue::Hole(), MemSpaceType::OLD_SPACE);
factory->NewSOldSpaceTaggedArray(512, JSTaggedValue::Hole());
[[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread);
[[maybe_unused]] JSHandle<TaggedArray> array = factory->NewTaggedArray(1024, JSTaggedValue::Hole(),
MemSpaceType::OLD_SPACE);
[[maybe_unused]] JSHandle<TaggedArray> sArray = factory->NewSOldSpaceTaggedArray(1024,
JSTaggedValue::Hole());
if (i%340 == 0) {
idleGCTrigger->NotifyVsyncIdleStart();
}
}
EXPECT_TRUE(idleGCTrigger->GetExpectedMemoryReclamationSize() >= 0);
idleGCTrigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::FULL_GC);
EXPECT_TRUE(idleGCTrigger->GetExpectedMemoryReclamationSize() >= 0);
idleGCTrigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::SHARED_FULL_GC);
int afterLocalGCCount = heap->GetEcmaGCStats()->GetGCCount();
int afterSharedGCCount = sHeap->GetEcmaGCStats()->GetGCCount();
EXPECT_TRUE(afterLocalGCCount - baseLocalGCCount < 10);
EXPECT_TRUE(afterSharedGCCount - baseSharedGCCount < 10);
heap->CollectGarbage(TriggerGCType::FULL_GC);
}
#endif
HWTEST_F_L0(GCTest, AdjustCapacity)
{
#if defined(PANDA_TARGET_ARM64)
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
SemiSpace * space = heap->GetNewSpace();
EXPECT_EQ(space->GetSurvivalObjectSize(), 0);
{
[[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread);
for (int i = 0; i < 300; i++) {
[[maybe_unused]] JSHandle<TaggedArray> array = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(
10 * 1024, JSTaggedValue::Hole(), MemSpaceType::SEMI_SPACE);
}
}
EXPECT_GT(space->GetSurvivalObjectSize(), 0);
EXPECT_FALSE(space->AdjustCapacity(0, thread));
size_t size = space->GetInitialCapacity() * GROW_OBJECT_SURVIVAL_RATE / 2;
EXPECT_FALSE(space->AdjustCapacity(size, thread));
space->SetInitialCapacity(space->GetSurvivalObjectSize() / GROW_OBJECT_SURVIVAL_RATE - 1);
size = space->GetSurvivalObjectSize() / GROW_OBJECT_SURVIVAL_RATE - 1;
size_t oldMaxCapacity = space->GetMaximumCapacity();
space->SetMaximumCapacity(space->GetInitialCapacity());
EXPECT_TRUE(space->AdjustCapacity(size, thread));
space->SetMaximumCapacity(oldMaxCapacity);
EXPECT_TRUE(space->AdjustCapacity(size, thread));
#endif
}
HWTEST_F_L0(GCTest, NativeMemAllocInSensitive)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
heap->NotifyHighSensitive(true);
for (size_t i = 0; i < 20; i++) {
[[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread);
factory->NewJSArrayBuffer(300 * 1024 * 1024);
}
EXPECT_TRUE(heap->GetGlobalNativeSize() < 1 * 1024 * 1024* 1024);
}
HWTEST_F_L0(GCTest, RecordAllocationForIdleTest001)
{
SharedHeap *heap = SharedHeap::GetInstance();
SharedMemController *controller = new SharedMemController(heap);
controller->RecordAllocationForIdle();
controller->RecordAllocationForIdle();
}
HWTEST_F_L0(GCTest, RecordAllocationForIdleTest002)
{
SharedHeap *heap = SharedHeap::GetInstance();
SharedMemController *controller = new SharedMemController(heap);
controller->RecordAllocationForIdle();
size_t before = heap->GetHeapObjectSize();
heap->ReclaimForAppSpawn();
size_t after = heap->GetHeapObjectSize();
ASSERT_NE(before, after);
controller->RecordAllocationForIdle();
}
HWTEST_F_L0(GCTest, PrintGCStatisticTest001)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
int prop = 1 << 15;
heap->GetEcmaVM()->GetJSOptions().SetArkProperties(prop);
ASSERT_EQ(heap->GetEcmaVM()->GetJSOptions().EnableGCTracer(), true);
GCStats *stats = new GCStats(heap);
stats->PrintGCStatistic();
prop = 1 << 14;
heap->GetEcmaVM()->GetJSOptions().SetArkProperties(prop);
ASSERT_EQ(heap->GetEcmaVM()->GetJSOptions().EnableGCTracer(), false);
stats->PrintGCStatistic();
SharedHeap *sHeap = SharedHeap::GetInstance();
SharedGCStats *stats1 = new SharedGCStats(sHeap, true);
stats1->PrintGCStatistic();
}
HWTEST_F_L0(GCTest, GCReasonToStringTest001)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
GCStats *stats = new GCStats(heap);
ASSERT_EQ(strcmp(stats->GCReasonToString(GCReason::SWITCH_BACKGROUND), "Switch to background"), 0);
ASSERT_EQ(strcmp(stats->GCReasonToString(GCReason::EXTERNAL_TRIGGER), "Externally triggered"), 0);
ASSERT_EQ(strcmp(stats->GCReasonToString(GCReason::WORKER_DESTRUCTION), "Worker Destruction"), 0);
ASSERT_EQ(strcmp(stats->GCReasonToString(GCReason::TRIGGER_BY_ARKUI), "Trigger by ArkUI"), 0);
ASSERT_EQ(strcmp(stats->GCReasonToString(GCReason::TRIGGER_BY_ABILITY), "Trigger by AbilityRuntime"), 0);
ASSERT_EQ(strcmp(stats->GCReasonToString(GCReason::TRIGGER_BY_MEM_TOOLS), "Trigger by Mem tools"), 0);
ASSERT_EQ(strcmp(stats->GCReasonToString(GCReason::TRIGGER_BY_TASKPOOL), "Trigger by taskPool"), 0);
ASSERT_EQ(strcmp(stats->GCReasonToString(GCReason::NATIVE_LIMIT), "Native reach limit"), 0);
ASSERT_EQ(strcmp(stats->GCReasonToString(GCReason::SHARED_LIMIT), "Shared reach limit"), 0);
ASSERT_EQ(strcmp(stats->GCReasonToString(GCReason::IDLE_NATIVE), "Idle time task by native"), 0);
ASSERT_EQ(strcmp(stats->GCReasonToString(GCReason::HANDLE_MARKING_FINISHED), "ConcurrentMark finished"), 0);
ASSERT_EQ(strcmp(stats->MarkReasonToString(MarkReason::IDLE), "Idle time task"), 0);
ASSERT_EQ(strcmp(stats->MarkReasonToString(MarkReason::EXIT_HIGH_SENSITIVE), "Exit high sensitive"), 0);
ASSERT_EQ(strcmp(stats->MarkReasonToString(MarkReason::EXTERNAL_TRIGGER), "Externally triggered"), 0);
ASSERT_EQ(strcmp(stats->MarkReasonToString(MarkReason::WORKER_DESTRUCTION), "Worker Destruction"), 0);
ASSERT_EQ(strcmp(stats->MarkReasonToString(MarkReason::TRIGGER_BY_JS), "Trigger by JS"), 0);
ASSERT_EQ(strcmp(stats->MarkReasonToString(MarkReason::HINT_GC), "Trigger by hint"), 0);
ASSERT_EQ(strcmp(stats->MarkReasonToString(MarkReason::NATIVE_LIMIT), "Native reach limit"), 0);
ASSERT_EQ(strcmp(stats->MarkReasonToString(MarkReason::SHARED_LIMIT), "Shared reach limit"), 0);
ASSERT_EQ(strcmp(stats->MarkReasonToString(MarkReason::EXIT_SERIALIZE), "Exit serialize"), 0);
}
HWTEST_F_L0(GCTest, PrintGCMemoryStatisticTest002)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
heap->SetMarkType(MarkType::MARK_YOUNG);
GCStats *stats = new GCStats(heap);
stats->RecordStatisticBeforeGC(TriggerGCType::YOUNG_GC, GCReason::TRIGGER_BY_ARKUI);
stats->PrintGCMemoryStatistic();
}
HWTEST_F_L0(GCTest, CheckIfNeedPrintTest001)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
heap->SetMarkType(MarkType::MARK_YOUNG);
GCStats *stats = new GCStats(heap);
stats->SetRecordData(RecordData::YOUNG_COUNT, 1);
stats->PrintStatisticResult();
}
HWTEST_F_L0(GCTest, PrintGCSummaryStatisticTest001)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
heap->SetMarkType(MarkType::MARK_YOUNG);
GCStats *stats = new GCStats(heap);
stats->PrintStatisticResult();
}
HWTEST_F_L0(GCTest, CalculateGrowingFactorTest001)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
heap->SetMemGrowingType(MemGrowingType::CONSERVATIVE);
auto controller = new MemController(heap);
ASSERT_EQ(controller->CalculateGrowingFactor(1, 1), 2.0);
}
HWTEST_F_L0(GCTest, CalculateGrowingFactorTest002)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
heap->SetMemGrowingType(MemGrowingType::PRESSURE);
auto controller = new MemController(heap);
ASSERT_EQ(controller->CalculateGrowingFactor(1, 1), 1.1);
}
HWTEST_F_L0(GCTest, CalculateGrowingFactorTest003)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
heap->SetMemGrowingType(MemGrowingType::CONSERVATIVE);
auto controller = new MemController(heap);
ASSERT_EQ(controller->CalculateGrowingFactor(1, 1), 2.0);
}
HWTEST_F_L0(GCTest, StopCalculationAfterGCTest001)
{
if constexpr (G_USE_CMS_GC) {
return;
}
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
auto controller = new MemController(heap);
std::this_thread::sleep_for(std::chrono::milliseconds(10));
controller->StartCalculationBeforeGC();
ASSERT_NE(controller->GetNewSpaceAllocSizeSinceGC(), 0);
ASSERT_NE(controller->GetOldSpaceAllocSizeSinceGC(), 0);
controller->StopCalculationAfterGC(TriggerGCType::YOUNG_GC);
ASSERT_EQ(controller->GetNewSpaceAllocSizeSinceGC(), 0);
ASSERT_EQ(controller->GetOldSpaceAllocSizeSinceGC(), 0);
}
HWTEST_F_L0(GCTest, RecordAllocationForIdleTest003)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
auto controller = new MemController(heap);
controller->RecordAllocationForIdle();
}
HWTEST_F_L0(GCTest, WaitAllTasksFinishedTest001)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
heap->GetJSThread()->SetMarkStatus(MarkStatus::MARKING);
heap->WaitAllTasksFinished();
}
HWTEST_F_L0(GCTest, WaitAllTasksFinishedTest002)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
heap->GetJSThread()->SetMarkStatus(MarkStatus::MARKING);
heap->GetConcurrentMarker()->Mark();
heap->WaitAllTasksFinished();
}
HWTEST_F_L0(GCTest, ChangeGCParamsTest002)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
heap->SetMemGrowingType(MemGrowingType::HIGH_THROUGHPUT);
ASSERT_EQ(heap->GetMemGrowingType(), MemGrowingType::HIGH_THROUGHPUT);
}
HWTEST_F_L0(GCTest, NotifyWarmStartFalse001)
{
#ifndef PANDA_TARGET_32
auto heap = const_cast<ecmascript::Heap *>(thread->GetEcmaVM()->GetHeap());
EXPECT_TRUE(heap->AllowWarmStartGcRestrain());
heap->TriggerConcurrentMarking();
EXPECT_FALSE(heap->AllowWarmStartGcRestrain());
#endif
}
HWTEST_F_L0(GCTest, NotifyWarmStartFalse002)
{
auto heap = const_cast<ecmascript::Heap *>(thread->GetEcmaVM()->GetHeap());
EXPECT_TRUE(heap->AllowWarmStartGcRestrain());
heap->NotifyPostFork();
EXPECT_FALSE(heap->AllowWarmStartGcRestrain());
}
HWTEST_F_L0(GCTest, GetGCStatisticTypeTest001)
{
EXPECT_STREQ(TestableGCStats::GetGCStatisticType(GCType::SHARED_GC), "Shared GC");
EXPECT_STREQ(TestableGCStats::GetGCStatisticType(GCType::SHARED_PARTIAL_GC), "Shared GC");
EXPECT_STREQ(TestableGCStats::GetGCStatisticType(GCType::SHARED_FULL_GC), "Shared GC");
EXPECT_STREQ(TestableGCStats::GetGCStatisticType(GCType::PARTIAL_YOUNG_GC), "Local GC");
EXPECT_STREQ(TestableGCStats::GetGCStatisticType(GCType::PARTIAL_OLD_GC), "Local GC");
EXPECT_STREQ(TestableGCStats::GetGCStatisticType(GCType::LOCAL_CC), "Local GC");
EXPECT_STREQ(TestableGCStats::GetGCStatisticType(GCType::COMPRESS_GC), "Local GC");
EXPECT_STREQ(TestableGCStats::GetGCStatisticType(GCType::CMS_GC), "Local GC");
EXPECT_STREQ(TestableGCStats::GetGCStatisticType(GCType::OTHER), "UnknownType");
}
HWTEST_F_L0(GCTest, GetGCStatisticDataTest001)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
TestableGCStats stats(heap);
stats.SetRecordData(RecordData::YOUNG_COUNT, 2);
stats.SetRecordDuration(RecordDuration::YOUNG_MIN_PAUSE, 3.5f);
stats.SetRecordDuration(RecordDuration::YOUNG_MAX_PAUSE, 8.5f);
stats.SetRecordDuration(RecordDuration::YOUNG_TOTAL_PAUSE, 12.0f);
stats.SetRecordData(RecordData::OLD_COUNT, 1);
stats.SetRecordDuration(RecordDuration::OLD_MIN_PAUSE, 5.0f);
stats.SetRecordDuration(RecordDuration::OLD_MAX_PAUSE, 9.0f);
stats.SetRecordDuration(RecordDuration::OLD_TOTAL_PAUSE, 5.0f);
stats.SetRecordData(RecordData::LOCAL_CC_COUNT, 1);
stats.SetRecordDuration(RecordDuration::LOCAL_CC_MIN_PAUSE, 2.0f);
stats.SetRecordDuration(RecordDuration::LOCAL_CC_MAX_PAUSE, 4.0f);
stats.SetRecordDuration(RecordDuration::LOCAL_CC_TOTAL_PAUSE, 2.0f);
stats.SetGCTypeForTest(GCType::PARTIAL_YOUNG_GC);
stats.RecordGCStatisticStart();
stats.RecordGCStatisticEnd();
GCStatisticData gcStatistic = stats.GetGCStatistic();
EXPECT_EQ(gcStatistic.count, 4U);
EXPECT_FLOAT_EQ(gcStatistic.maxPause, 9.0f);
EXPECT_FLOAT_EQ(gcStatistic.minPause, 2.0f);
EXPECT_FLOAT_EQ(gcStatistic.totalPause, 19.0f);
EXPECT_NE(gcStatistic.lastStartTime, 0U);
EXPECT_NE(gcStatistic.lastEndTime, 0U);
EXPECT_STREQ(gcStatistic.lastType, "Local GC");
}
HWTEST_F_L0(GCTest, GetGCStatisticTypeTest002)
{
EXPECT_STREQ(TestableGCStats::GetGCStatisticType(GCType::SHARED_GC), "Shared GC");
EXPECT_STREQ(TestableGCStats::GetGCStatisticType(GCType::SHARED_PARTIAL_GC), "Shared GC");
EXPECT_STREQ(TestableGCStats::GetGCStatisticType(GCType::SHARED_FULL_GC), "Shared GC");
EXPECT_STREQ(TestableGCStats::GetGCStatisticType(GCType::PARTIAL_YOUNG_GC), "Local GC");
EXPECT_STREQ(TestableGCStats::GetGCStatisticType(GCType::PARTIAL_OLD_GC), "Local GC");
EXPECT_STREQ(TestableGCStats::GetGCStatisticType(GCType::LOCAL_CC), "Local GC");
EXPECT_STREQ(TestableGCStats::GetGCStatisticType(GCType::COMPRESS_GC), "Local GC");
EXPECT_STREQ(TestableGCStats::GetGCStatisticType(GCType::CMS_GC), "Local GC");
EXPECT_STREQ(TestableGCStats::GetGCStatisticType(GCType::GLOBAL_GC), "Shared GC");
EXPECT_STREQ(TestableGCStats::GetGCStatisticType(GCType::OTHER), "UnknownType");
}
HWTEST_F_L0(GCTest, GetGCStatisticDataTest002)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
TestableGCStats stats(heap);
stats.SetGCTypeForTest(GCType::OTHER);
stats.RecordGCStatisticStart();
stats.RecordGCStatisticEnd();
GCStatisticData gcStatistic = stats.GetGCStatistic();
EXPECT_EQ(gcStatistic.count, 0U);
EXPECT_FLOAT_EQ(gcStatistic.maxPause, 0.0f);
EXPECT_FLOAT_EQ(gcStatistic.minPause, 0.0f);
EXPECT_FLOAT_EQ(gcStatistic.totalPause, 0.0f);
EXPECT_NE(gcStatistic.lastStartTime, 0U);
EXPECT_NE(gcStatistic.lastEndTime, 0U);
EXPECT_STREQ(gcStatistic.lastType, "UnknownType");
}
HWTEST_F_L0(GCTest, GetGCStatisticDataTest003)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
TestableGCStats stats(heap);
stats.SetRecordData(RecordData::YOUNG_COUNT, 5);
stats.SetRecordDuration(RecordDuration::YOUNG_MIN_PAUSE, 1.5f);
stats.SetRecordDuration(RecordDuration::YOUNG_MAX_PAUSE, 9.5f);
stats.SetRecordDuration(RecordDuration::YOUNG_TOTAL_PAUSE, 20.0f);
stats.SetGCTypeForTest(GCType::PARTIAL_YOUNG_GC);
stats.RecordGCStatisticStart();
stats.RecordGCStatisticEnd();
GCStatisticData gcStatistic = stats.GetGCStatistic();
EXPECT_EQ(gcStatistic.count, 5U);
EXPECT_FLOAT_EQ(gcStatistic.maxPause, 9.5f);
EXPECT_FLOAT_EQ(gcStatistic.minPause, 1.5f);
EXPECT_FLOAT_EQ(gcStatistic.totalPause, 20.0f);
EXPECT_STREQ(gcStatistic.lastType, "Local GC");
}
HWTEST_F_L0(GCTest, GetGCStatisticDataTest004)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
TestableGCStats stats(heap);
stats.SetRecordData(RecordData::OLD_COUNT, 3);
stats.SetRecordDuration(RecordDuration::OLD_MIN_PAUSE, 4.0f);
stats.SetRecordDuration(RecordDuration::OLD_MAX_PAUSE, 12.0f);
stats.SetRecordDuration(RecordDuration::OLD_TOTAL_PAUSE, 18.5f);
stats.SetGCTypeForTest(GCType::PARTIAL_OLD_GC);
stats.RecordGCStatisticStart();
stats.RecordGCStatisticEnd();
GCStatisticData gcStatistic = stats.GetGCStatistic();
EXPECT_EQ(gcStatistic.count, 3U);
EXPECT_FLOAT_EQ(gcStatistic.maxPause, 12.0f);
EXPECT_FLOAT_EQ(gcStatistic.minPause, 4.0f);
EXPECT_FLOAT_EQ(gcStatistic.totalPause, 18.5f);
EXPECT_STREQ(gcStatistic.lastType, "Local GC");
}
HWTEST_F_L0(GCTest, GetGCStatisticDataTest005)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
TestableGCStats stats(heap);
stats.SetRecordData(RecordData::COMPRESS_COUNT, 2);
stats.SetRecordDuration(RecordDuration::COMPRESS_MIN_PAUSE, 6.0f);
stats.SetRecordDuration(RecordDuration::COMPRESS_MAX_PAUSE, 14.0f);
stats.SetRecordDuration(RecordDuration::COMPRESS_TOTAL_PAUSE, 21.0f);
stats.SetGCTypeForTest(GCType::COMPRESS_GC);
stats.RecordGCStatisticStart();
stats.RecordGCStatisticEnd();
GCStatisticData gcStatistic = stats.GetGCStatistic();
EXPECT_EQ(gcStatistic.count, 2U);
EXPECT_FLOAT_EQ(gcStatistic.maxPause, 14.0f);
EXPECT_FLOAT_EQ(gcStatistic.minPause, 6.0f);
EXPECT_FLOAT_EQ(gcStatistic.totalPause, 21.0f);
EXPECT_STREQ(gcStatistic.lastType, "Local GC");
}
HWTEST_F_L0(GCTest, GetGCStatisticDataTest006)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
TestableGCStats stats(heap);
stats.SetRecordData(RecordData::LOCAL_CC_COUNT, 4);
stats.SetRecordDuration(RecordDuration::LOCAL_CC_MIN_PAUSE, 2.5f);
stats.SetRecordDuration(RecordDuration::LOCAL_CC_MAX_PAUSE, 6.5f);
stats.SetRecordDuration(RecordDuration::LOCAL_CC_TOTAL_PAUSE, 16.0f);
stats.SetGCTypeForTest(GCType::LOCAL_CC);
stats.RecordGCStatisticStart();
stats.RecordGCStatisticEnd();
GCStatisticData gcStatistic = stats.GetGCStatistic();
EXPECT_EQ(gcStatistic.count, 4U);
EXPECT_FLOAT_EQ(gcStatistic.maxPause, 6.5f);
EXPECT_FLOAT_EQ(gcStatistic.minPause, 2.5f);
EXPECT_FLOAT_EQ(gcStatistic.totalPause, 16.0f);
EXPECT_STREQ(gcStatistic.lastType, "Local GC");
}
HWTEST_F_L0(GCTest, GetGCStatisticDataTest007)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
TestableGCStats stats(heap);
stats.SetRecordData(RecordData::SHARED_COUNT, 7);
stats.SetRecordDuration(RecordDuration::SHARED_MIN_PAUSE, 3.0f);
stats.SetRecordDuration(RecordDuration::SHARED_MAX_PAUSE, 10.0f);
stats.SetRecordDuration(RecordDuration::SHARED_TOTAL_PAUSE, 35.0f);
stats.SetGCTypeForTest(GCType::SHARED_GC);
stats.RecordGCStatisticStart();
stats.RecordGCStatisticEnd();
GCStatisticData gcStatistic = stats.GetGCStatistic();
EXPECT_EQ(gcStatistic.count, 7U);
EXPECT_FLOAT_EQ(gcStatistic.maxPause, 10.0f);
EXPECT_FLOAT_EQ(gcStatistic.minPause, 3.0f);
EXPECT_FLOAT_EQ(gcStatistic.totalPause, 35.0f);
EXPECT_STREQ(gcStatistic.lastType, "Shared GC");
}
HWTEST_F_L0(GCTest, GetGCStatisticDataTest008)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
TestableGCStats stats(heap);
stats.SetRecordData(RecordData::SWEEP_COUNT, 8);
stats.SetRecordDuration(RecordDuration::SWEEP_MIN_PAUSE, 4.5f);
stats.SetRecordDuration(RecordDuration::SWEEP_MAX_PAUSE, 11.5f);
stats.SetRecordDuration(RecordDuration::SWEEP_TOTAL_PAUSE, 40.0f);
stats.SetGCTypeForTest(GCType::CMS_GC);
stats.RecordGCStatisticStart();
stats.RecordGCStatisticEnd();
GCStatisticData gcStatistic = stats.GetGCStatistic();
EXPECT_EQ(gcStatistic.count, 8U);
EXPECT_FLOAT_EQ(gcStatistic.maxPause, 11.5f);
EXPECT_FLOAT_EQ(gcStatistic.minPause, 4.5f);
EXPECT_FLOAT_EQ(gcStatistic.totalPause, 40.0f);
EXPECT_STREQ(gcStatistic.lastType, "Local GC");
}
HWTEST_F_L0(GCTest, GetGCStatisticDataTest009)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
TestableGCStats stats(heap);
stats.SetRecordData(RecordData::YOUNG_COUNT, 1);
stats.SetRecordDuration(RecordDuration::YOUNG_MIN_PAUSE, 8.0f);
stats.SetRecordDuration(RecordDuration::YOUNG_MAX_PAUSE, 11.0f);
stats.SetRecordDuration(RecordDuration::YOUNG_TOTAL_PAUSE, 11.0f);
stats.SetRecordData(RecordData::OLD_COUNT, 2);
stats.SetRecordDuration(RecordDuration::OLD_MIN_PAUSE, 7.0f);
stats.SetRecordDuration(RecordDuration::OLD_MAX_PAUSE, 12.0f);
stats.SetRecordDuration(RecordDuration::OLD_TOTAL_PAUSE, 19.0f);
stats.SetRecordData(RecordData::COMPRESS_COUNT, 3);
stats.SetRecordDuration(RecordDuration::COMPRESS_MIN_PAUSE, 6.0f);
stats.SetRecordDuration(RecordDuration::COMPRESS_MAX_PAUSE, 13.0f);
stats.SetRecordDuration(RecordDuration::COMPRESS_TOTAL_PAUSE, 24.0f);
stats.SetRecordData(RecordData::LOCAL_CC_COUNT, 4);
stats.SetRecordDuration(RecordDuration::LOCAL_CC_MIN_PAUSE, 5.0f);
stats.SetRecordDuration(RecordDuration::LOCAL_CC_MAX_PAUSE, 14.0f);
stats.SetRecordDuration(RecordDuration::LOCAL_CC_TOTAL_PAUSE, 28.0f);
stats.SetRecordData(RecordData::SHARED_COUNT, 5);
stats.SetRecordDuration(RecordDuration::SHARED_MIN_PAUSE, 4.0f);
stats.SetRecordDuration(RecordDuration::SHARED_MAX_PAUSE, 15.0f);
stats.SetRecordDuration(RecordDuration::SHARED_TOTAL_PAUSE, 33.0f);
stats.SetRecordData(RecordData::SWEEP_COUNT, 6);
stats.SetRecordDuration(RecordDuration::SWEEP_MIN_PAUSE, 3.0f);
stats.SetRecordDuration(RecordDuration::SWEEP_MAX_PAUSE, 16.0f);
stats.SetRecordDuration(RecordDuration::SWEEP_TOTAL_PAUSE, 39.0f);
stats.SetGCTypeForTest(GCType::SHARED_FULL_GC);
stats.RecordGCStatisticStart();
stats.RecordGCStatisticEnd();
GCStatisticData gcStatistic = stats.GetGCStatistic();
EXPECT_EQ(gcStatistic.count, 21U);
EXPECT_FLOAT_EQ(gcStatistic.maxPause, 16.0f);
EXPECT_FLOAT_EQ(gcStatistic.minPause, 3.0f);
EXPECT_FLOAT_EQ(gcStatistic.totalPause, 154.0f);
EXPECT_STREQ(gcStatistic.lastType, "Shared GC");
}
HWTEST_F_L0(GCTest, GetGCStatisticDataTest010)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
TestableGCStats stats(heap);
stats.SetRecordData(RecordData::YOUNG_COUNT, 0);
stats.SetRecordDuration(RecordDuration::YOUNG_MIN_PAUSE, 1.0f);
stats.SetRecordDuration(RecordDuration::YOUNG_MAX_PAUSE, 99.0f);
stats.SetRecordDuration(RecordDuration::YOUNG_TOTAL_PAUSE, 100.0f);
stats.SetRecordData(RecordData::OLD_COUNT, 2);
stats.SetRecordDuration(RecordDuration::OLD_MIN_PAUSE, 4.0f);
stats.SetRecordDuration(RecordDuration::OLD_MAX_PAUSE, 7.0f);
stats.SetRecordDuration(RecordDuration::OLD_TOTAL_PAUSE, 10.0f);
stats.SetGCTypeForTest(GCType::PARTIAL_OLD_GC);
stats.RecordGCStatisticStart();
stats.RecordGCStatisticEnd();
GCStatisticData gcStatistic = stats.GetGCStatistic();
EXPECT_EQ(gcStatistic.count, 2U);
EXPECT_FLOAT_EQ(gcStatistic.maxPause, 7.0f);
EXPECT_FLOAT_EQ(gcStatistic.minPause, 4.0f);
EXPECT_FLOAT_EQ(gcStatistic.totalPause, 10.0f);
EXPECT_STREQ(gcStatistic.lastType, "Local GC");
}
HWTEST_F_L0(GCTest, GetGCStatisticDataTest011)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
TestableGCStats stats(heap);
stats.SetGCTypeForTest(GCType::PARTIAL_YOUNG_GC);
stats.RecordGCStatisticStart();
stats.RecordGCStatisticEnd();
GCStatisticData gcStatistic = stats.GetGCStatistic();
EXPECT_EQ(gcStatistic.count, 0U);
EXPECT_NE(gcStatistic.lastStartTime, 0U);
EXPECT_NE(gcStatistic.lastEndTime, 0U);
EXPECT_LE(gcStatistic.lastStartTime, gcStatistic.lastEndTime);
EXPECT_STREQ(gcStatistic.lastType, "Local GC");
}
HWTEST_F_L0(GCTest, GetGCStatisticDataTest012)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
TestableGCStats stats(heap);
stats.SetGCTypeForTest(GCType::SHARED_PARTIAL_GC);
stats.RecordGCStatisticStart();
stats.RecordGCStatisticEnd();
GCStatisticData gcStatistic = stats.GetGCStatistic();
EXPECT_EQ(gcStatistic.count, 0U);
EXPECT_NE(gcStatistic.lastStartTime, 0U);
EXPECT_NE(gcStatistic.lastEndTime, 0U);
EXPECT_LE(gcStatistic.lastStartTime, gcStatistic.lastEndTime);
EXPECT_STREQ(gcStatistic.lastType, "Shared GC");
}
HWTEST_F_L0(GCTest, GetGCStatisticDataTest013)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
TestableGCStats stats(heap);
stats.SetGCTypeForTest(GCType::GLOBAL_GC);
stats.RecordGCStatisticStart();
stats.RecordGCStatisticEnd();
GCStatisticData gcStatistic = stats.GetGCStatistic();
EXPECT_EQ(gcStatistic.count, 0U);
EXPECT_NE(gcStatistic.lastStartTime, 0U);
EXPECT_NE(gcStatistic.lastEndTime, 0U);
EXPECT_LE(gcStatistic.lastStartTime, gcStatistic.lastEndTime);
EXPECT_STREQ(gcStatistic.lastType, "Shared GC");
}
HWTEST_F_L0(GCTest, MergeGCStatisticTest001)
{
GCStatisticData localStats;
localStats.count = 0;
localStats.maxPause = 1.0f;
localStats.minPause = 0.0f;
localStats.totalPause = 1.0f;
localStats.lastStartTime = 10;
localStats.lastEndTime = 20;
localStats.lastType = "Local GC";
GCStatisticData sharedStats;
sharedStats.count = 2;
sharedStats.maxPause = 5.0f;
sharedStats.minPause = 2.0f;
sharedStats.totalPause = 7.0f;
sharedStats.lastStartTime = 30;
sharedStats.lastEndTime = 40;
sharedStats.lastType = "Shared GC";
GCStatisticData merged = TestableGCStats::MergeGCStatistic(localStats, sharedStats);
EXPECT_EQ(merged.count, 2U);
EXPECT_FLOAT_EQ(merged.maxPause, 5.0f);
EXPECT_FLOAT_EQ(merged.minPause, 2.0f);
EXPECT_FLOAT_EQ(merged.totalPause, 8.0f);
EXPECT_EQ(merged.lastStartTime, 30U);
EXPECT_EQ(merged.lastEndTime, 40U);
EXPECT_STREQ(merged.lastType, "Shared GC");
}
HWTEST_F_L0(GCTest, MergeGCStatisticTest002)
{
GCStatisticData localStats;
localStats.count = 3;
localStats.maxPause = 6.0f;
localStats.minPause = 1.5f;
localStats.totalPause = 9.0f;
localStats.lastStartTime = 50;
localStats.lastEndTime = 80;
localStats.lastType = "Local GC";
GCStatisticData sharedStats;
sharedStats.count = 0;
sharedStats.maxPause = 4.0f;
sharedStats.minPause = 0.0f;
sharedStats.totalPause = 2.0f;
sharedStats.lastStartTime = 40;
sharedStats.lastEndTime = 70;
sharedStats.lastType = "Shared GC";
GCStatisticData merged = TestableGCStats::MergeGCStatistic(localStats, sharedStats);
EXPECT_EQ(merged.count, 3U);
EXPECT_FLOAT_EQ(merged.maxPause, 6.0f);
EXPECT_FLOAT_EQ(merged.minPause, 1.5f);
EXPECT_FLOAT_EQ(merged.totalPause, 11.0f);
EXPECT_EQ(merged.lastStartTime, 50U);
EXPECT_EQ(merged.lastEndTime, 80U);
EXPECT_STREQ(merged.lastType, "Local GC");
}
HWTEST_F_L0(GCTest, MergeGCStatisticTest003)
{
GCStatisticData localStats;
localStats.count = 2;
localStats.maxPause = 3.0f;
localStats.minPause = 2.5f;
localStats.totalPause = 5.0f;
localStats.lastStartTime = 100;
localStats.lastEndTime = 120;
localStats.lastType = "Local GC";
GCStatisticData sharedStats;
sharedStats.count = 4;
sharedStats.maxPause = 7.0f;
sharedStats.minPause = 1.0f;
sharedStats.totalPause = 8.0f;
sharedStats.lastStartTime = 90;
sharedStats.lastEndTime = 110;
sharedStats.lastType = "Shared GC";
GCStatisticData merged = TestableGCStats::MergeGCStatistic(localStats, sharedStats);
EXPECT_EQ(merged.count, 6U);
EXPECT_FLOAT_EQ(merged.maxPause, 7.0f);
EXPECT_FLOAT_EQ(merged.minPause, 1.0f);
EXPECT_FLOAT_EQ(merged.totalPause, 13.0f);
EXPECT_EQ(merged.lastStartTime, 100U);
EXPECT_EQ(merged.lastEndTime, 120U);
EXPECT_STREQ(merged.lastType, "Local GC");
sharedStats.lastStartTime = 130;
sharedStats.lastEndTime = 140;
merged = TestableGCStats::MergeGCStatistic(localStats, sharedStats);
EXPECT_EQ(merged.lastStartTime, 130U);
EXPECT_EQ(merged.lastEndTime, 140U);
EXPECT_STREQ(merged.lastType, "Shared GC");
}
HWTEST_F_L0(GCTest, MergeGCStatisticTest004)
{
GCStatisticData localStats;
localStats.count = 0;
localStats.maxPause = 2.0f;
localStats.minPause = 0.0f;
localStats.totalPause = 1.0f;
localStats.lastStartTime = 100;
localStats.lastEndTime = 120;
localStats.lastType = "Local GC";
GCStatisticData sharedStats;
sharedStats.count = 0;
sharedStats.maxPause = 5.0f;
sharedStats.minPause = 0.0f;
sharedStats.totalPause = 3.0f;
sharedStats.lastStartTime = 50;
sharedStats.lastEndTime = 150;
sharedStats.lastType = "Shared GC";
GCStatisticData merged = TestableGCStats::MergeGCStatistic(localStats, sharedStats);
EXPECT_EQ(merged.count, 0U);
EXPECT_FLOAT_EQ(merged.maxPause, 5.0f);
EXPECT_FLOAT_EQ(merged.minPause, 0.0f);
EXPECT_FLOAT_EQ(merged.totalPause, 4.0f);
EXPECT_EQ(merged.lastStartTime, 100U);
EXPECT_EQ(merged.lastEndTime, 150U);
EXPECT_STREQ(merged.lastType, "Local GC");
}
HWTEST_F_L0(GCTest, MergeGCStatisticTest005)
{
GCStatisticData localStats;
localStats.count = 0;
localStats.maxPause = 1.0f;
localStats.minPause = 0.0f;
localStats.totalPause = 2.0f;
localStats.lastStartTime = 10;
localStats.lastEndTime = 80;
localStats.lastType = "Local GC";
GCStatisticData sharedStats;
sharedStats.count = 0;
sharedStats.maxPause = 2.0f;
sharedStats.minPause = 0.0f;
sharedStats.totalPause = 5.0f;
sharedStats.lastStartTime = 90;
sharedStats.lastEndTime = 70;
sharedStats.lastType = "Shared GC";
GCStatisticData merged = TestableGCStats::MergeGCStatistic(localStats, sharedStats);
EXPECT_EQ(merged.count, 0U);
EXPECT_FLOAT_EQ(merged.maxPause, 2.0f);
EXPECT_FLOAT_EQ(merged.minPause, 0.0f);
EXPECT_FLOAT_EQ(merged.totalPause, 7.0f);
EXPECT_EQ(merged.lastStartTime, 90U);
EXPECT_EQ(merged.lastEndTime, 80U);
EXPECT_STREQ(merged.lastType, "Shared GC");
}
HWTEST_F_L0(GCTest, MergeGCStatisticTest006)
{
GCStatisticData localStats;
localStats.count = 4;
localStats.maxPause = 6.0f;
localStats.minPause = 1.0f;
localStats.totalPause = 11.0f;
localStats.lastStartTime = 200;
localStats.lastEndTime = 210;
localStats.lastType = "Local GC";
GCStatisticData sharedStats;
sharedStats.count = 5;
sharedStats.maxPause = 9.0f;
sharedStats.minPause = 0.5f;
sharedStats.totalPause = 15.0f;
sharedStats.lastStartTime = 200;
sharedStats.lastEndTime = 260;
sharedStats.lastType = "Shared GC";
GCStatisticData merged = TestableGCStats::MergeGCStatistic(localStats, sharedStats);
EXPECT_EQ(merged.count, 9U);
EXPECT_FLOAT_EQ(merged.maxPause, 9.0f);
EXPECT_FLOAT_EQ(merged.minPause, 0.5f);
EXPECT_FLOAT_EQ(merged.totalPause, 26.0f);
EXPECT_EQ(merged.lastStartTime, 200U);
EXPECT_EQ(merged.lastEndTime, 260U);
EXPECT_STREQ(merged.lastType, "Local GC");
}
HWTEST_F_L0(GCTest, MergeGCStatisticTest007)
{
GCStatisticData localStats;
localStats.count = 2;
localStats.maxPause = 10.0f;
localStats.minPause = 3.0f;
localStats.totalPause = 14.0f;
localStats.lastStartTime = 400;
localStats.lastEndTime = 405;
localStats.lastType = "Local GC";
GCStatisticData sharedStats;
sharedStats.count = 6;
sharedStats.maxPause = 12.0f;
sharedStats.minPause = 2.0f;
sharedStats.totalPause = 28.0f;
sharedStats.lastStartTime = 401;
sharedStats.lastEndTime = 403;
sharedStats.lastType = "Shared GC";
GCStatisticData merged = TestableGCStats::MergeGCStatistic(localStats, sharedStats);
EXPECT_EQ(merged.count, 8U);
EXPECT_FLOAT_EQ(merged.maxPause, 12.0f);
EXPECT_FLOAT_EQ(merged.minPause, 2.0f);
EXPECT_FLOAT_EQ(merged.totalPause, 42.0f);
EXPECT_EQ(merged.lastStartTime, 401U);
EXPECT_EQ(merged.lastEndTime, 405U);
EXPECT_STREQ(merged.lastType, "Shared GC");
}
HWTEST_F_L0(GCTest, MergeGCStatisticTest008)
{
GCStatisticData localStats;
localStats.count = 1;
localStats.maxPause = 0.0f;
localStats.minPause = 0.0f;
localStats.totalPause = 0.0f;
localStats.lastStartTime = 1;
localStats.lastEndTime = 2;
localStats.lastType = "Local GC";
GCStatisticData sharedStats;
sharedStats.count = 3;
sharedStats.maxPause = 4.5f;
sharedStats.minPause = 1.5f;
sharedStats.totalPause = 6.0f;
sharedStats.lastStartTime = 3;
sharedStats.lastEndTime = 4;
sharedStats.lastType = "Shared GC";
GCStatisticData merged = TestableGCStats::MergeGCStatistic(localStats, sharedStats);
EXPECT_EQ(merged.count, 4U);
EXPECT_FLOAT_EQ(merged.maxPause, 4.5f);
EXPECT_FLOAT_EQ(merged.minPause, 0.0f);
EXPECT_FLOAT_EQ(merged.totalPause, 6.0f);
EXPECT_EQ(merged.lastStartTime, 3U);
EXPECT_EQ(merged.lastEndTime, 4U);
EXPECT_STREQ(merged.lastType, "Shared GC");
}
HWTEST_F_L0(GCTest, IsLongGCTest001)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
TestableGCStats stats(heap);
EXPECT_FALSE(stats.IsLongGC(GCReason::IDLE, false, true,
static_cast<float>(GCKeyStats::GC_BACKGROUD_IDLE_LONG_TIME)));
EXPECT_TRUE(stats.IsLongGC(GCReason::IDLE, false, true,
static_cast<float>(GCKeyStats::GC_BACKGROUD_IDLE_LONG_TIME) + 0.1f));
EXPECT_FALSE(stats.IsLongGC(GCReason::IDLE, false, false, static_cast<float>(GCKeyStats::GC_IDLE_LONG_TIME)));
EXPECT_TRUE(stats.IsLongGC(GCReason::IDLE, false, false,
static_cast<float>(GCKeyStats::GC_IDLE_LONG_TIME) + 0.1f));
EXPECT_FALSE(stats.IsLongGC(GCReason::OTHER, false, false,
static_cast<float>(GCKeyStats::GC_NOT_SENSITIVE_LONG_TIME)));
EXPECT_TRUE(stats.IsLongGC(GCReason::OTHER, false, false,
static_cast<float>(GCKeyStats::GC_NOT_SENSITIVE_LONG_TIME) + 0.1f));
EXPECT_FALSE(stats.IsLongGC(GCReason::OTHER, true, false,
static_cast<float>(GCKeyStats::GC_SENSITIVE_LONG_TIME)));
EXPECT_TRUE(stats.IsLongGC(GCReason::OTHER, true, false,
static_cast<float>(GCKeyStats::GC_SENSITIVE_LONG_TIME) + 0.1f));
}
HWTEST_F_L0(GCTest, IsLongGCTest002)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
TestableGCStats stats(heap);
EXPECT_FALSE(stats.IsLongGC(GCReason::OTHER, false, true,
static_cast<float>(GCKeyStats::GC_BACKGROUD_LONG_TIME)));
EXPECT_TRUE(stats.IsLongGC(GCReason::OTHER, false, true,
static_cast<float>(GCKeyStats::GC_BACKGROUD_LONG_TIME) + 0.1f));
EXPECT_FALSE(stats.IsLongGC(GCReason::TRIGGER_BY_JS, false, true,
static_cast<float>(GCKeyStats::GC_BACKGROUD_LONG_TIME)));
EXPECT_TRUE(stats.IsLongGC(GCReason::TRIGGER_BY_JS, false, true,
static_cast<float>(GCKeyStats::GC_BACKGROUD_LONG_TIME) + 0.1f));
}
HWTEST_F_L0(GCTest, IsLongGCTest003)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
TestableGCStats stats(heap);
EXPECT_FALSE(stats.IsLongGC(GCReason::IDLE, true, false,
static_cast<float>(GCKeyStats::GC_SENSITIVE_LONG_TIME)));
EXPECT_TRUE(stats.IsLongGC(GCReason::IDLE, true, false,
static_cast<float>(GCKeyStats::GC_SENSITIVE_LONG_TIME) + 0.1f));
EXPECT_FALSE(stats.IsLongGC(GCReason::IDLE, true, true,
static_cast<float>(GCKeyStats::GC_SENSITIVE_LONG_TIME)));
EXPECT_TRUE(stats.IsLongGC(GCReason::IDLE, true, true,
static_cast<float>(GCKeyStats::GC_SENSITIVE_LONG_TIME) + 0.1f));
}
HWTEST_F_L0(GCTest, IsLongGCTest004)
{
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
TestableGCStats stats(heap);
EXPECT_FALSE(stats.IsLongGC(GCReason::IDLE_NATIVE, false, false,
static_cast<float>(GCKeyStats::GC_IDLE_LONG_TIME)));
EXPECT_TRUE(stats.IsLongGC(GCReason::IDLE_NATIVE, false, false,
static_cast<float>(GCKeyStats::GC_IDLE_LONG_TIME) + 0.1f));
EXPECT_FALSE(stats.IsLongGC(GCReason::IDLE_NATIVE, false, true,
static_cast<float>(GCKeyStats::GC_BACKGROUD_IDLE_LONG_TIME)));
EXPECT_TRUE(stats.IsLongGC(GCReason::IDLE_NATIVE, false, true,
static_cast<float>(GCKeyStats::GC_BACKGROUD_IDLE_LONG_TIME) + 0.1f));
}
}