1/*
2 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
3 * Copyright (c) 2018 SAP SE. All rights reserved.
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 only, as
8 * published by the Free Software Foundation.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 *
24 */
25#include "precompiled.hpp"
26
27#include "memory/metaspace/metachunk.hpp"
28#include "memory/metaspace/metaspaceCommon.hpp"
29#include "memory/metaspace/metaspaceStatistics.hpp"
30#include "utilities/debug.hpp"
31#include "utilities/globalDefinitions.hpp"
32#include "utilities/ostream.hpp"
33
34namespace metaspace {
35
36// FreeChunksStatistics methods
37
38FreeChunksStatistics::FreeChunksStatistics()
39: _num(0), _cap(0)
40{}
41
42void FreeChunksStatistics::reset() {
43 _num = 0; _cap = 0;
44}
45
46void FreeChunksStatistics::add(uintx n, size_t s) {
47 _num += n; _cap += s;
48}
49
50void FreeChunksStatistics::add(const FreeChunksStatistics& other) {
51 _num += other._num;
52 _cap += other._cap;
53}
54
55void FreeChunksStatistics::print_on(outputStream* st, size_t scale) const {
56 st->print(UINTX_FORMAT, _num);
57 st->print(" chunks, total capacity ");
58 print_scaled_words(st, _cap, scale);
59}
60
61// ChunkManagerStatistics methods
62
63void ChunkManagerStatistics::reset() {
64 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) {
65 _chunk_stats[i].reset();
66 }
67}
68
69size_t ChunkManagerStatistics::total_capacity() const {
70 return _chunk_stats[SpecializedIndex].cap() +
71 _chunk_stats[SmallIndex].cap() +
72 _chunk_stats[MediumIndex].cap() +
73 _chunk_stats[HumongousIndex].cap();
74}
75
76void ChunkManagerStatistics::print_on(outputStream* st, size_t scale) const {
77 FreeChunksStatistics totals;
78 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) {
79 st->cr();
80 st->print("%12s chunks: ", chunk_size_name(i));
81 if (_chunk_stats[i].num() > 0) {
82 st->print(UINTX_FORMAT_W(4) ", capacity ", _chunk_stats[i].num());
83 print_scaled_words(st, _chunk_stats[i].cap(), scale);
84 } else {
85 st->print("(none)");
86 }
87 totals.add(_chunk_stats[i]);
88 }
89 st->cr();
90 st->print("%19s: " UINTX_FORMAT_W(4) ", capacity=", "Total", totals.num());
91 print_scaled_words(st, totals.cap(), scale);
92 st->cr();
93}
94
95// UsedChunksStatistics methods
96
97UsedChunksStatistics::UsedChunksStatistics()
98: _num(0), _cap(0), _used(0), _free(0), _waste(0), _overhead(0)
99{}
100
101void UsedChunksStatistics::reset() {
102 _num = 0;
103 _cap = _overhead = _used = _free = _waste = 0;
104}
105
106void UsedChunksStatistics::add(const UsedChunksStatistics& other) {
107 _num += other._num;
108 _cap += other._cap;
109 _used += other._used;
110 _free += other._free;
111 _waste += other._waste;
112 _overhead += other._overhead;
113 DEBUG_ONLY(check_sanity());
114}
115
116void UsedChunksStatistics::print_on(outputStream* st, size_t scale) const {
117 int col = st->position();
118 st->print(UINTX_FORMAT_W(4) " chunk%s, ", _num, _num != 1 ? "s" : "");
119 if (_num > 0) {
120 col += 14; st->fill_to(col);
121
122 print_scaled_words(st, _cap, scale, 5);
123 st->print(" capacity, ");
124
125 col += 18; st->fill_to(col);
126 print_scaled_words_and_percentage(st, _used, _cap, scale, 5);
127 st->print(" used, ");
128
129 col += 20; st->fill_to(col);
130 print_scaled_words_and_percentage(st, _free, _cap, scale, 5);
131 st->print(" free, ");
132
133 col += 20; st->fill_to(col);
134 print_scaled_words_and_percentage(st, _waste, _cap, scale, 5);
135 st->print(" waste, ");
136
137 col += 20; st->fill_to(col);
138 print_scaled_words_and_percentage(st, _overhead, _cap, scale, 5);
139 st->print(" overhead");
140 }
141 DEBUG_ONLY(check_sanity());
142}
143
144#ifdef ASSERT
145void UsedChunksStatistics::check_sanity() const {
146 assert(_overhead == (Metachunk::overhead() * _num), "Sanity: Overhead.");
147 assert(_cap == _used + _free + _waste + _overhead, "Sanity: Capacity.");
148}
149#endif
150
151// SpaceManagerStatistics methods
152
153SpaceManagerStatistics::SpaceManagerStatistics() { reset(); }
154
155void SpaceManagerStatistics::reset() {
156 for (int i = 0; i < NumberOfInUseLists; i ++) {
157 _chunk_stats[i].reset();
158 _free_blocks_num = 0; _free_blocks_cap_words = 0;
159 }
160}
161
162void SpaceManagerStatistics::add_free_blocks_info(uintx num, size_t cap) {
163 _free_blocks_num += num;
164 _free_blocks_cap_words += cap;
165}
166
167void SpaceManagerStatistics::add(const SpaceManagerStatistics& other) {
168 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) {
169 _chunk_stats[i].add(other._chunk_stats[i]);
170 }
171 _free_blocks_num += other._free_blocks_num;
172 _free_blocks_cap_words += other._free_blocks_cap_words;
173}
174
175// Returns total chunk statistics over all chunk types.
176UsedChunksStatistics SpaceManagerStatistics::totals() const {
177 UsedChunksStatistics stat;
178 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) {
179 stat.add(_chunk_stats[i]);
180 }
181 return stat;
182}
183
184void SpaceManagerStatistics::print_on(outputStream* st, size_t scale, bool detailed) const {
185 streamIndentor sti(st);
186 if (detailed) {
187 st->cr_indent();
188 st->print("Usage by chunk type:");
189 {
190 streamIndentor sti2(st);
191 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) {
192 st->cr_indent();
193 st->print("%15s: ", chunk_size_name(i));
194 if (_chunk_stats[i].num() == 0) {
195 st->print(" (none)");
196 } else {
197 _chunk_stats[i].print_on(st, scale);
198 }
199 }
200
201 st->cr_indent();
202 st->print("%15s: ", "-total-");
203 totals().print_on(st, scale);
204 }
205 if (_free_blocks_num > 0) {
206 st->cr_indent();
207 st->print("deallocated: " UINTX_FORMAT " blocks with ", _free_blocks_num);
208 print_scaled_words(st, _free_blocks_cap_words, scale);
209 }
210 } else {
211 totals().print_on(st, scale);
212 st->print(", ");
213 st->print("deallocated: " UINTX_FORMAT " blocks with ", _free_blocks_num);
214 print_scaled_words(st, _free_blocks_cap_words, scale);
215 }
216}
217
218// ClassLoaderMetaspaceStatistics methods
219
220ClassLoaderMetaspaceStatistics::ClassLoaderMetaspaceStatistics() { reset(); }
221
222void ClassLoaderMetaspaceStatistics::reset() {
223 nonclass_sm_stats().reset();
224 if (Metaspace::using_class_space()) {
225 class_sm_stats().reset();
226 }
227}
228
229// Returns total space manager statistics for both class and non-class metaspace
230SpaceManagerStatistics ClassLoaderMetaspaceStatistics::totals() const {
231 SpaceManagerStatistics stats;
232 stats.add(nonclass_sm_stats());
233 if (Metaspace::using_class_space()) {
234 stats.add(class_sm_stats());
235 }
236 return stats;
237}
238
239void ClassLoaderMetaspaceStatistics::add(const ClassLoaderMetaspaceStatistics& other) {
240 nonclass_sm_stats().add(other.nonclass_sm_stats());
241 if (Metaspace::using_class_space()) {
242 class_sm_stats().add(other.class_sm_stats());
243 }
244}
245
246void ClassLoaderMetaspaceStatistics::print_on(outputStream* st, size_t scale, bool detailed) const {
247 streamIndentor sti(st);
248 st->cr_indent();
249 if (Metaspace::using_class_space()) {
250 st->print("Non-Class: ");
251 }
252 nonclass_sm_stats().print_on(st, scale, detailed);
253 if (detailed) {
254 st->cr();
255 }
256 if (Metaspace::using_class_space()) {
257 st->cr_indent();
258 st->print(" Class: ");
259 class_sm_stats().print_on(st, scale, detailed);
260 if (detailed) {
261 st->cr();
262 }
263 st->cr_indent();
264 st->print(" Both: ");
265 totals().print_on(st, scale, detailed);
266 if (detailed) {
267 st->cr();
268 }
269 }
270 st->cr();
271}
272
273} // end namespace metaspace
274
275
276
277