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