14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License.
54514f5e3Sopenharmony_ci * You may obtain a copy of the License at
64514f5e3Sopenharmony_ci *
74514f5e3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84514f5e3Sopenharmony_ci *
94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and
134514f5e3Sopenharmony_ci * limitations under the License.
144514f5e3Sopenharmony_ci */
154514f5e3Sopenharmony_ci
164514f5e3Sopenharmony_ci#include "ecmascript/mem/gc_key_stats.h"
174514f5e3Sopenharmony_ci
184514f5e3Sopenharmony_ci#include <iostream>
194514f5e3Sopenharmony_ci#include <cstring>
204514f5e3Sopenharmony_ci
214514f5e3Sopenharmony_ci#ifdef ENABLE_HISYSEVENT
224514f5e3Sopenharmony_ci#include "hisysevent.h"
234514f5e3Sopenharmony_ci#endif
244514f5e3Sopenharmony_ci#if !defined(PANDA_TARGET_WINDOWS) && !defined(PANDA_TARGET_MACOS) && !defined(PANDA_TARGET_IOS)
254514f5e3Sopenharmony_ci#include <sys/resource.h>
264514f5e3Sopenharmony_ci#endif
274514f5e3Sopenharmony_ci
284514f5e3Sopenharmony_ci#include "ecmascript/mem/heap-inl.h"
294514f5e3Sopenharmony_ci#include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
304514f5e3Sopenharmony_ci
314514f5e3Sopenharmony_cinamespace panda::ecmascript {
324514f5e3Sopenharmony_ciusing PGOProfilerManager = pgo::PGOProfilerManager;
334514f5e3Sopenharmony_ciusing Clock = std::chrono::high_resolution_clock;
344514f5e3Sopenharmony_ci
354514f5e3Sopenharmony_cibool GCKeyStats::CheckIfMainThread() const
364514f5e3Sopenharmony_ci{
374514f5e3Sopenharmony_ci#if !defined(PANDA_TARGET_WINDOWS) && !defined(PANDA_TARGET_MACOS) && !defined(PANDA_TARGET_IOS)
384514f5e3Sopenharmony_ci    return getpid() == syscall(SYS_gettid);
394514f5e3Sopenharmony_ci#else
404514f5e3Sopenharmony_ci    return true;
414514f5e3Sopenharmony_ci#endif
424514f5e3Sopenharmony_ci}
434514f5e3Sopenharmony_ci
444514f5e3Sopenharmony_cibool GCKeyStats::CheckIfKeyPauseTime() const
454514f5e3Sopenharmony_ci{
464514f5e3Sopenharmony_ci    return gcStats_->GetScopeDuration(GCStats::Scope::ScopeId::TotalGC) >= KEY_PAUSE_TIME;
474514f5e3Sopenharmony_ci}
484514f5e3Sopenharmony_ci
494514f5e3Sopenharmony_civoid GCKeyStats::AddGCStatsToKey()
504514f5e3Sopenharmony_ci{
514514f5e3Sopenharmony_ci    LOG_GC(DEBUG) << "GCKeyStats AddGCStatsToKey!";
524514f5e3Sopenharmony_ci
534514f5e3Sopenharmony_ci    recordCount_++;
544514f5e3Sopenharmony_ci
554514f5e3Sopenharmony_ci    AddRecordDataStats(RecordKeyData::GC_TOTAL_MEM_USED,
564514f5e3Sopenharmony_ci        SizeToIntKB(gcStats_->GetRecordData(RecordData::END_OBJ_SIZE)));
574514f5e3Sopenharmony_ci    AddRecordDataStats(RecordKeyData::GC_TOTAL_MEM_COMMITTED,
584514f5e3Sopenharmony_ci        SizeToIntKB(gcStats_->GetRecordData(RecordData::END_COMMIT_SIZE)));
594514f5e3Sopenharmony_ci    AddRecordDataStats(RecordKeyData::GC_ACTIVE_MEM_USED,
604514f5e3Sopenharmony_ci        SizeToIntKB(gcStats_->GetRecordData(RecordData::YOUNG_ALIVE_SIZE)));
614514f5e3Sopenharmony_ci    AddRecordDataStats(RecordKeyData::GC_ACTIVE_MEM_COMMITTED,
624514f5e3Sopenharmony_ci        SizeToIntKB(gcStats_->GetRecordData(RecordData::YOUNG_COMMIT_SIZE)));
634514f5e3Sopenharmony_ci    AddRecordDataStats(RecordKeyData::GC_OLD_MEM_USED,
644514f5e3Sopenharmony_ci        SizeToIntKB(gcStats_->GetRecordData(RecordData::OLD_ALIVE_SIZE)));
654514f5e3Sopenharmony_ci    AddRecordDataStats(RecordKeyData::GC_OLD_MEM_COMMITTED,
664514f5e3Sopenharmony_ci        SizeToIntKB(gcStats_->GetRecordData(RecordData::OLD_COMMIT_SIZE)));
674514f5e3Sopenharmony_ci
684514f5e3Sopenharmony_ci    AddRecordDataStats(RecordKeyData::GC_HUGE_MEM_USED,
694514f5e3Sopenharmony_ci        SizeToIntKB(heap_->GetHugeObjectSpace()->GetHeapObjectSize()));
704514f5e3Sopenharmony_ci    AddRecordDataStats(RecordKeyData::GC_HUGE_MEM_COMMITTED,
714514f5e3Sopenharmony_ci        SizeToIntKB(heap_->GetHugeObjectSpace()->GetCommittedSize()));
724514f5e3Sopenharmony_ci
734514f5e3Sopenharmony_ci    AddRecordKeyDuration(RecordKeyDuration::GC_TOTAL_TIME,
744514f5e3Sopenharmony_ci        gcStats_->GetScopeDuration(GCStats::Scope::ScopeId::TotalGC));
754514f5e3Sopenharmony_ci    AddRecordKeyDuration(RecordKeyDuration::GC_MARK_TIME,
764514f5e3Sopenharmony_ci        gcStats_->GetScopeDuration(GCStats::Scope::ScopeId::Mark));
774514f5e3Sopenharmony_ci    AddRecordKeyDuration(RecordKeyDuration::GC_EVACUATE_TIME,
784514f5e3Sopenharmony_ci        gcStats_->GetScopeDuration(GCStats::Scope::ScopeId::Evacuate));
794514f5e3Sopenharmony_ci
804514f5e3Sopenharmony_ci    if (CheckLastSendTimeIfSend() && CheckCountIfSend()) {
814514f5e3Sopenharmony_ci        SendSysEvent();
824514f5e3Sopenharmony_ci        PrintKeyStatisticResult();
834514f5e3Sopenharmony_ci        InitializeRecordList();
844514f5e3Sopenharmony_ci    }
854514f5e3Sopenharmony_ci}
864514f5e3Sopenharmony_ci
874514f5e3Sopenharmony_civoid GCKeyStats::SendSysEvent() const
884514f5e3Sopenharmony_ci{
894514f5e3Sopenharmony_ci#ifdef ENABLE_HISYSEVENT
904514f5e3Sopenharmony_ci    int32_t ret = HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::ARKTS_RUNTIME,
914514f5e3Sopenharmony_ci        "ARK_STATS_GC",
924514f5e3Sopenharmony_ci        OHOS::HiviewDFX::HiSysEvent::EventType::STATISTIC,
934514f5e3Sopenharmony_ci        "BUNDLE_NAME", PGOProfilerManager::GetInstance()->GetBundleName(),
944514f5e3Sopenharmony_ci        "PID", getpid(),
954514f5e3Sopenharmony_ci        "TID", syscall(SYS_gettid),
964514f5e3Sopenharmony_ci        "GC_TOTAL_COUNT", gcCount_,
974514f5e3Sopenharmony_ci        "GC_TOTAL_TIME", static_cast<int>(GetRecordKeyDuration(RecordKeyDuration::GC_TOTAL_TIME)),
984514f5e3Sopenharmony_ci        "GC_MARK_TIME", static_cast<int>(GetRecordKeyDuration(RecordKeyDuration::GC_MARK_TIME)),
994514f5e3Sopenharmony_ci        "GC_EVACUATE_TIME", static_cast<int>(GetRecordKeyDuration(RecordKeyDuration::GC_EVACUATE_TIME)),
1004514f5e3Sopenharmony_ci        "GC_LONG_TIME", recordCount_,
1014514f5e3Sopenharmony_ci        "GC_TOTAL_MEM_USED", GetRecordDataStats(RecordKeyData::GC_TOTAL_MEM_USED),
1024514f5e3Sopenharmony_ci        "GC_TOTAL_MEM_COMMITTED", GetRecordDataStats(RecordKeyData::GC_TOTAL_MEM_COMMITTED),
1034514f5e3Sopenharmony_ci        "GC_ACTIVE_MEM_USED", GetRecordDataStats(RecordKeyData::GC_ACTIVE_MEM_USED),
1044514f5e3Sopenharmony_ci        "GC_ACTIVE_MEM_COMMITTED", GetRecordDataStats(RecordKeyData::GC_ACTIVE_MEM_COMMITTED),
1054514f5e3Sopenharmony_ci        "GC_OLD_MEM_USED", GetRecordDataStats(RecordKeyData::GC_OLD_MEM_USED),
1064514f5e3Sopenharmony_ci        "GC_OLD_MEM_COMMITTED", GetRecordDataStats(RecordKeyData::GC_OLD_MEM_COMMITTED),
1074514f5e3Sopenharmony_ci        "GC_HUGE_MEM_USED", GetRecordDataStats(RecordKeyData::GC_HUGE_MEM_USED),
1084514f5e3Sopenharmony_ci        "GC_HUGE_MEM_COMMITTED", GetRecordDataStats(RecordKeyData::GC_HUGE_MEM_COMMITTED));
1094514f5e3Sopenharmony_ci    if (ret != 0) {
1104514f5e3Sopenharmony_ci        LOG_GC(ERROR) << "GCKeyStats HiSysEventWrite Failed! ret = " << ret;
1114514f5e3Sopenharmony_ci    }
1124514f5e3Sopenharmony_ci#endif
1134514f5e3Sopenharmony_ci}
1144514f5e3Sopenharmony_ci
1154514f5e3Sopenharmony_civoid GCKeyStats::SendSysEventBeforeDump(std::string type, size_t limitSize, size_t activeMemory) const
1164514f5e3Sopenharmony_ci{
1174514f5e3Sopenharmony_ci#ifdef ENABLE_HISYSEVENT
1184514f5e3Sopenharmony_ci    int32_t ret = HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::FRAMEWORK,
1194514f5e3Sopenharmony_ci        "ARK_STATS_DUMP",
1204514f5e3Sopenharmony_ci        OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
1214514f5e3Sopenharmony_ci        "PID", getprocpid(),
1224514f5e3Sopenharmony_ci        "TID", syscall(SYS_gettid),
1234514f5e3Sopenharmony_ci        "PROCESS_NAME", PGOProfilerManager::GetInstance()->GetBundleName(),
1244514f5e3Sopenharmony_ci        "LIMITSIZE", limitSize,
1254514f5e3Sopenharmony_ci        "ACTIVE_MEMORY", activeMemory,
1264514f5e3Sopenharmony_ci        "TYPE", type);
1274514f5e3Sopenharmony_ci    if (ret != 0) {
1284514f5e3Sopenharmony_ci        LOG_GC(ERROR) << "GCKeyStats SendSysEventBeforeDump Failed! ret = " << ret;
1294514f5e3Sopenharmony_ci    }
1304514f5e3Sopenharmony_ci#else
1314514f5e3Sopenharmony_ci    LOG_GC(INFO) << "GCKeyStats type: " << type << ", limitSize: " << limitSize << ", activeMemory: " << activeMemory;
1324514f5e3Sopenharmony_ci#endif
1334514f5e3Sopenharmony_ci}
1344514f5e3Sopenharmony_ci
1354514f5e3Sopenharmony_civoid GCKeyStats::PrintKeyStatisticResult() const
1364514f5e3Sopenharmony_ci{
1374514f5e3Sopenharmony_ci    LOG_GC(INFO) << "/******************* GCKeyStats HiSysEvent statistic: *******************/";
1384514f5e3Sopenharmony_ci}
1394514f5e3Sopenharmony_ci
1404514f5e3Sopenharmony_civoid GCKeyStats::InitializeRecordList()
1414514f5e3Sopenharmony_ci{
1424514f5e3Sopenharmony_ci    gcCount_ = 0;
1434514f5e3Sopenharmony_ci    recordCount_ = 0;
1444514f5e3Sopenharmony_ci    std::fill(recordDurationStats_, recordDurationStats_ + (uint8_t)RecordKeyDuration::NUM_OF_KEY_DURATION, 0.0f);
1454514f5e3Sopenharmony_ci    std::fill(recordDataStats_, recordDataStats_ + (uint8_t)RecordKeyData::NUM_OF_KEY_DATA, 0);
1464514f5e3Sopenharmony_ci    lastSendTimestamp_ = Clock::now();
1474514f5e3Sopenharmony_ci}
1484514f5e3Sopenharmony_ci
1494514f5e3Sopenharmony_ci} // namespace panda::ecmascript