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 #ifndef ECMASCRIPT_MEM_GC_KEY_STATS_H 17 #define ECMASCRIPT_MEM_GC_KEY_STATS_H 18 19 #include <ctime> 20 #include <chrono> 21 #include <string> 22 23 #include "ecmascript/common_enum.h" 24 #include "ecmascript/mem/mem_common.h" 25 #include "ecmascript/log_wrapper.h" 26 27 #include "libpandabase/macros.h" 28 29 namespace panda::ecmascript { 30 using Clock = std::chrono::high_resolution_clock; 31 class Heap; 32 class GCStats; 33 34 enum class RecordKeyData : uint8_t { 35 GC_TOTAL_MEM_USED = 0, 36 GC_TOTAL_MEM_COMMITTED, 37 GC_ACTIVE_MEM_USED, 38 GC_ACTIVE_MEM_COMMITTED, 39 GC_OLD_MEM_USED, 40 GC_OLD_MEM_COMMITTED, 41 GC_HUGE_MEM_USED, 42 GC_HUGE_MEM_COMMITTED, 43 NUM_OF_KEY_DATA, 44 FIRST_DATA = GC_TOTAL_MEM_USED, 45 }; 46 47 enum class RecordKeyDuration : uint8_t { 48 GC_TOTAL_TIME = 0, 49 GC_MARK_TIME, 50 GC_EVACUATE_TIME, 51 NUM_OF_KEY_DURATION, 52 FIRST_DATA = GC_TOTAL_TIME, 53 }; 54 55 class GCKeyStats { 56 static constexpr size_t KEY_PAUSE_TIME = 20; // ms 57 static constexpr int NEED_SEND_TIMES = 200; 58 static constexpr int MIN_SEND_INTERVAL = 60; // seconds 59 public: GCKeyStats(const Heap * heap)60 explicit GCKeyStats(const Heap *heap) : heap_(heap) {} GCKeyStats(const Heap * heap,GCStats * gcStats)61 GCKeyStats(const Heap *heap, GCStats *gcStats) : heap_(heap), 62 gcStats_(gcStats) {} 63 ~GCKeyStats() = default; 64 65 static constexpr int GC_SENSITIVE_LONG_TIME = 33; 66 static constexpr int GC_NOT_SENSITIVE_LONG_TIME = 33; 67 static constexpr int GC_IDLE_LONG_TIME = 200; 68 static constexpr int GC_BACKGROUD_LONG_TIME = 200; 69 static constexpr int GC_BACKGROUD_IDLE_LONG_TIME = 500; 70 void AddGCStatsToKey(); 71 bool CheckIfMainThread() const; 72 bool CheckIfKeyPauseTime() const; 73 void SendSysEventBeforeDump(std::string type, size_t limitSize, size_t activeMemory, 74 const std::string &eventConfig) const; 75 int32_t SendSysEventDataSize(std::vector<std::string> filePaths, std::vector<uint64_t> fileSizes) const; 76 void ProcessLongGCEvent(); IsIdle(GCReason gcReason)77 static bool IsIdle(GCReason gcReason) 78 { 79 if (gcReason == GCReason::IDLE || gcReason == GCReason::IDLE_NATIVE) { 80 return true; 81 } 82 return false; 83 } 84 IncGCCount()85 void IncGCCount() 86 { 87 gcCount_++; 88 } 89 AddRecordDataStats(RecordKeyData idx,int value)90 void AddRecordDataStats(RecordKeyData idx, int value) 91 { 92 recordDataStats_[GetRecordDataStatsIndex(idx)] += value; 93 } 94 GetRecordDataStats(RecordKeyData idx)95 int GetRecordDataStats(RecordKeyData idx) const 96 { 97 return recordDataStats_[GetRecordDataStatsIndex(idx)]; 98 } 99 AddRecordKeyDuration(RecordKeyDuration idx,float value)100 void AddRecordKeyDuration(RecordKeyDuration idx, float value) 101 { 102 recordDurationStats_[GetRecordKeyDurationIndex(idx)] += value; 103 } 104 GetRecordKeyDuration(RecordKeyDuration idx)105 float GetRecordKeyDuration(RecordKeyDuration idx) const 106 { 107 return recordDurationStats_[GetRecordKeyDurationIndex(idx)]; 108 } 109 110 private: 111 void SendSysEvent() const; 112 void InitializeRecordList(); 113 void PrintKeyStatisticResult() const; 114 double GetCpuUsage(); 115 void SendLongGCEvent(); CheckLastSendTimeIfSend()116 bool CheckLastSendTimeIfSend() const 117 { 118 return lastSendTimestamp_ == Clock::time_point::min() || 119 std::chrono::duration_cast<std::chrono::seconds>(Clock::now() - lastSendTimestamp_).count() >= 120 MIN_SEND_INTERVAL; 121 } 122 CheckCountIfSend()123 bool CheckCountIfSend() const 124 { 125 return recordCount_ >= NEED_SEND_TIMES; 126 } 127 GetRecordDataStatsIndex(RecordKeyData dataIdx)128 int GetRecordDataStatsIndex(RecordKeyData dataIdx) const 129 { 130 return (int)dataIdx - (int)RecordKeyData::FIRST_DATA; 131 } 132 GetRecordKeyDurationIndex(RecordKeyDuration dataIdx)133 int GetRecordKeyDurationIndex(RecordKeyDuration dataIdx) const 134 { 135 return (int)dataIdx - (int)RecordKeyDuration::FIRST_DATA; 136 } 137 SizeToIntKB(size_t size)138 int SizeToIntKB(size_t size) const 139 { 140 return static_cast<int>(size / 1_KB); 141 } 142 143 const Heap *heap_; 144 GCStats *gcStats_; 145 146 int gcCount_{0}; 147 int recordCount_{0}; 148 Clock::time_point lastSendTimestamp_; 149 float recordDurationStats_[(uint8_t)RecordKeyDuration::NUM_OF_KEY_DURATION]{0.0f}; 150 int recordDataStats_[(uint8_t)RecordKeyData::NUM_OF_KEY_DATA]{0}; 151 }; 152 153 } // namespace panda::ecmascript 154 #endif // ECMASCRIPT_MEM_GC_KEY_STATS_H