• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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