1 /**
2 * Copyright (c) 2021-2022 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 "runtime/mem/mem_stats_additional_info.h"
17
18 #include "runtime/include/class-inl.h"
19 #include "runtime/include/runtime.h"
20
21 namespace panda::mem {
22
GetAdditionalStatistics(HeapManager * heap_manager)23 PandaString MemStatsAdditionalInfo::GetAdditionalStatistics(HeapManager *heap_manager)
24 {
25 PandaVector<Class *> classes;
26 auto class_linker = Runtime::GetCurrent()->GetClassLinker();
27 class_linker->EnumerateClasses([&classes](Class *cls) {
28 classes.push_back(cls);
29 return true;
30 });
31
32 PandaVector<uint64_t> footprint_of_classes(classes.size(), 0U);
33 heap_manager->CountInstances(classes, true, footprint_of_classes.data());
34
35 PandaMultiMap<uint64_t, Class *> footprint_to_class;
36 for (size_t index = 0; index < classes.size(); ++index) {
37 footprint_to_class.insert({footprint_of_classes[index], classes[index]});
38 }
39
40 PandaStringStream statistic;
41 PandaMultiMap<uint64_t, Class *>::reverse_iterator rit;
42 for (rit = footprint_to_class.rbegin(); rit != footprint_to_class.rend(); ++rit) {
43 if (rit->first == 0U) {
44 break;
45 }
46 auto clazz = rit->second;
47 statistic << "class: " << clazz->GetName() << ", footprint - " << rit->first << std::endl;
48 }
49 return statistic.str();
50 }
51
RecordGCPhaseStart(GCPhase phase)52 void MemStatsAdditionalInfo::RecordGCPhaseStart(GCPhase phase)
53 {
54 os::memory::LockHolder lk(phase_lock_);
55 if (current_phase_ != GCPhase::GC_PHASE_LAST) {
56 RecordGCPauseEnd();
57 }
58 phase_start_time_ = clock::now();
59 current_phase_ = phase;
60 }
61
RecordGCPhaseEnd()62 void MemStatsAdditionalInfo::RecordGCPhaseEnd()
63 {
64 os::memory::LockHolder lk(phase_lock_);
65 ASSERT(current_phase_ != GCPhase::GC_PHASE_LAST);
66
67 uint64_t phase_index = ToIndex(current_phase_);
68 duration phase_time = clock::now() - phase_start_time_;
69 if (phase_count_[phase_index] != 0) {
70 min_phase_time_[phase_index] = std::min(min_phase_time_[phase_index], phase_time);
71 max_phase_time_[phase_index] = std::max(max_phase_time_[phase_index], phase_time);
72 } else {
73 min_phase_time_[phase_index] = phase_time;
74 max_phase_time_[phase_index] = phase_time;
75 }
76 phase_count_[phase_index]++;
77 sum_phase_time_[phase_index] += phase_time;
78
79 current_phase_ = GCPhase::GC_PHASE_LAST;
80 }
81
GetMinGCPhaseTime(GCPhase phase)82 uint64_t MemStatsAdditionalInfo::GetMinGCPhaseTime(GCPhase phase)
83 {
84 os::memory::LockHolder lk(phase_lock_);
85 return std::chrono::duration_cast<std::chrono::milliseconds>(min_phase_time_[ToIndex(phase)]).count();
86 }
87
GetMaxGCPhaseTime(GCPhase phase)88 uint64_t MemStatsAdditionalInfo::GetMaxGCPhaseTime(GCPhase phase)
89 {
90 os::memory::LockHolder lk(phase_lock_);
91 return std::chrono::duration_cast<std::chrono::milliseconds>(max_phase_time_[ToIndex(phase)]).count();
92 }
93
GetAverageGCPhaseTime(GCPhase phase)94 uint64_t MemStatsAdditionalInfo::GetAverageGCPhaseTime(GCPhase phase)
95 {
96 os::memory::LockHolder lk(phase_lock_);
97 return phase_count_[ToIndex(phase)] != 0
98 ? static_cast<uint64_t>(
99 std::chrono::duration_cast<std::chrono::milliseconds>(sum_phase_time_[ToIndex(phase)]).count()) /
100 phase_count_[ToIndex(phase)]
101 : 0;
102 }
103
GetTotalGCPhaseTime(GCPhase phase)104 uint64_t MemStatsAdditionalInfo::GetTotalGCPhaseTime(GCPhase phase)
105 {
106 os::memory::LockHolder lk(phase_lock_);
107 return std::chrono::duration_cast<std::chrono::milliseconds>(sum_phase_time_[ToIndex(phase)]).count();
108 }
109
110 } // namespace panda::mem
111