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
31 namespace panda::ecmascript {
32 using PGOProfilerManager = pgo::PGOProfilerManager;
33 using Clock = std::chrono::high_resolution_clock;
34
CheckIfMainThread() const35 bool 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
CheckIfKeyPauseTime() const44 bool GCKeyStats::CheckIfKeyPauseTime() const
45 {
46 return gcStats_->GetScopeDuration(GCStats::Scope::ScopeId::TotalGC) >= KEY_PAUSE_TIME;
47 }
48
AddGCStatsToKey()49 void 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
SendSysEvent() const87 void 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
SendSysEventBeforeDump(std::string type, size_t limitSize, size_t activeMemory) const115 void 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
PrintKeyStatisticResult() const135 void GCKeyStats::PrintKeyStatisticResult() const
136 {
137 LOG_GC(INFO) << "/******************* GCKeyStats HiSysEvent statistic: *******************/";
138 }
139
InitializeRecordList()140 void 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