1/* 2 * Copyright (c) 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 16#include "ecmascript/mem/gc_key_stats.h" 17 18#include <iostream> 19#include <cstring> 20 21#ifdef ENABLE_HISYSEVENT 22#include "hisysevent.h" 23#endif 24#if !defined(PANDA_TARGET_WINDOWS) && !defined(PANDA_TARGET_MACOS) && !defined(PANDA_TARGET_IOS) 25#include <sys/resource.h> 26#endif 27 28#include "ecmascript/mem/heap-inl.h" 29#include "ecmascript/pgo_profiler/pgo_profiler_manager.h" 30 31namespace panda::ecmascript { 32using PGOProfilerManager = pgo::PGOProfilerManager; 33using Clock = std::chrono::high_resolution_clock; 34 35bool GCKeyStats::CheckIfMainThread() const 36{ 37#if !defined(PANDA_TARGET_WINDOWS) && !defined(PANDA_TARGET_MACOS) && !defined(PANDA_TARGET_IOS) 38 return getpid() == syscall(SYS_gettid); 39#else 40 return true; 41#endif 42} 43 44bool GCKeyStats::CheckIfKeyPauseTime() const 45{ 46 return gcStats_->GetScopeDuration(GCStats::Scope::ScopeId::TotalGC) >= KEY_PAUSE_TIME; 47} 48 49void GCKeyStats::AddGCStatsToKey() 50{ 51 LOG_GC(DEBUG) << "GCKeyStats AddGCStatsToKey!"; 52 53 recordCount_++; 54 55 AddRecordDataStats(RecordKeyData::GC_TOTAL_MEM_USED, 56 SizeToIntKB(gcStats_->GetRecordData(RecordData::END_OBJ_SIZE))); 57 AddRecordDataStats(RecordKeyData::GC_TOTAL_MEM_COMMITTED, 58 SizeToIntKB(gcStats_->GetRecordData(RecordData::END_COMMIT_SIZE))); 59 AddRecordDataStats(RecordKeyData::GC_ACTIVE_MEM_USED, 60 SizeToIntKB(gcStats_->GetRecordData(RecordData::YOUNG_ALIVE_SIZE))); 61 AddRecordDataStats(RecordKeyData::GC_ACTIVE_MEM_COMMITTED, 62 SizeToIntKB(gcStats_->GetRecordData(RecordData::YOUNG_COMMIT_SIZE))); 63 AddRecordDataStats(RecordKeyData::GC_OLD_MEM_USED, 64 SizeToIntKB(gcStats_->GetRecordData(RecordData::OLD_ALIVE_SIZE))); 65 AddRecordDataStats(RecordKeyData::GC_OLD_MEM_COMMITTED, 66 SizeToIntKB(gcStats_->GetRecordData(RecordData::OLD_COMMIT_SIZE))); 67 68 AddRecordDataStats(RecordKeyData::GC_HUGE_MEM_USED, 69 SizeToIntKB(heap_->GetHugeObjectSpace()->GetHeapObjectSize())); 70 AddRecordDataStats(RecordKeyData::GC_HUGE_MEM_COMMITTED, 71 SizeToIntKB(heap_->GetHugeObjectSpace()->GetCommittedSize())); 72 73 AddRecordKeyDuration(RecordKeyDuration::GC_TOTAL_TIME, 74 gcStats_->GetScopeDuration(GCStats::Scope::ScopeId::TotalGC)); 75 AddRecordKeyDuration(RecordKeyDuration::GC_MARK_TIME, 76 gcStats_->GetScopeDuration(GCStats::Scope::ScopeId::Mark)); 77 AddRecordKeyDuration(RecordKeyDuration::GC_EVACUATE_TIME, 78 gcStats_->GetScopeDuration(GCStats::Scope::ScopeId::Evacuate)); 79 80 if (CheckLastSendTimeIfSend() && CheckCountIfSend()) { 81 SendSysEvent(); 82 PrintKeyStatisticResult(); 83 InitializeRecordList(); 84 } 85} 86 87void GCKeyStats::SendSysEvent() const 88{ 89#ifdef ENABLE_HISYSEVENT 90 int32_t ret = HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::ARKTS_RUNTIME, 91 "ARK_STATS_GC", 92 OHOS::HiviewDFX::HiSysEvent::EventType::STATISTIC, 93 "BUNDLE_NAME", PGOProfilerManager::GetInstance()->GetBundleName(), 94 "PID", getpid(), 95 "TID", syscall(SYS_gettid), 96 "GC_TOTAL_COUNT", gcCount_, 97 "GC_TOTAL_TIME", static_cast<int>(GetRecordKeyDuration(RecordKeyDuration::GC_TOTAL_TIME)), 98 "GC_MARK_TIME", static_cast<int>(GetRecordKeyDuration(RecordKeyDuration::GC_MARK_TIME)), 99 "GC_EVACUATE_TIME", static_cast<int>(GetRecordKeyDuration(RecordKeyDuration::GC_EVACUATE_TIME)), 100 "GC_LONG_TIME", recordCount_, 101 "GC_TOTAL_MEM_USED", GetRecordDataStats(RecordKeyData::GC_TOTAL_MEM_USED), 102 "GC_TOTAL_MEM_COMMITTED", GetRecordDataStats(RecordKeyData::GC_TOTAL_MEM_COMMITTED), 103 "GC_ACTIVE_MEM_USED", GetRecordDataStats(RecordKeyData::GC_ACTIVE_MEM_USED), 104 "GC_ACTIVE_MEM_COMMITTED", GetRecordDataStats(RecordKeyData::GC_ACTIVE_MEM_COMMITTED), 105 "GC_OLD_MEM_USED", GetRecordDataStats(RecordKeyData::GC_OLD_MEM_USED), 106 "GC_OLD_MEM_COMMITTED", GetRecordDataStats(RecordKeyData::GC_OLD_MEM_COMMITTED), 107 "GC_HUGE_MEM_USED", GetRecordDataStats(RecordKeyData::GC_HUGE_MEM_USED), 108 "GC_HUGE_MEM_COMMITTED", GetRecordDataStats(RecordKeyData::GC_HUGE_MEM_COMMITTED)); 109 if (ret != 0) { 110 LOG_GC(ERROR) << "GCKeyStats HiSysEventWrite Failed! ret = " << ret; 111 } 112#endif 113} 114 115void GCKeyStats::SendSysEventBeforeDump(std::string type, size_t limitSize, size_t activeMemory) const 116{ 117#ifdef ENABLE_HISYSEVENT 118 int32_t ret = HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::FRAMEWORK, 119 "ARK_STATS_DUMP", 120 OHOS::HiviewDFX::HiSysEvent::EventType::FAULT, 121 "PID", getprocpid(), 122 "TID", syscall(SYS_gettid), 123 "PROCESS_NAME", PGOProfilerManager::GetInstance()->GetBundleName(), 124 "LIMITSIZE", limitSize, 125 "ACTIVE_MEMORY", activeMemory, 126 "TYPE", type); 127 if (ret != 0) { 128 LOG_GC(ERROR) << "GCKeyStats SendSysEventBeforeDump Failed! ret = " << ret; 129 } 130#else 131 LOG_GC(INFO) << "GCKeyStats type: " << type << ", limitSize: " << limitSize << ", activeMemory: " << activeMemory; 132#endif 133} 134 135void GCKeyStats::PrintKeyStatisticResult() const 136{ 137 LOG_GC(INFO) << "/******************* GCKeyStats HiSysEvent statistic: *******************/"; 138} 139 140void GCKeyStats::InitializeRecordList() 141{ 142 gcCount_ = 0; 143 recordCount_ = 0; 144 std::fill(recordDurationStats_, recordDurationStats_ + (uint8_t)RecordKeyDuration::NUM_OF_KEY_DURATION, 0.0f); 145 std::fill(recordDataStats_, recordDataStats_ + (uint8_t)RecordKeyData::NUM_OF_KEY_DATA, 0); 146 lastSendTimestamp_ = Clock::now(); 147} 148 149} // namespace panda::ecmascript