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
34 namespace metaspace {
35
36 // FreeChunksStatistics methods
37
38 FreeChunksStatistics::FreeChunksStatistics()
39 : _num(0), _cap(0)
40 {}
41
42 void FreeChunksStatistics::reset() {
43 _num = 0; _cap = 0;
44 }
45
46 void FreeChunksStatistics::add(uintx n, size_t s) {
47 _num += n; _cap += s;
48 }
49
50 void FreeChunksStatistics::add(const FreeChunksStatistics& other) {
51 _num += other._num;
52 _cap += other._cap;
53 }
54
55 void 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
63 void ChunkManagerStatistics::reset() {
64 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) {
65 _chunk_stats[i].reset();
66 }
67 }
68
69 size_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
76 void 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
97 UsedChunksStatistics::UsedChunksStatistics()
98 : _num(0), _cap(0), _used(0), _free(0), _waste(0), _overhead(0)
99 {}
100
101 void UsedChunksStatistics::reset() {
102 _num = 0;
103 _cap = _overhead = _used = _free = _waste = 0;
104 }
105
106 void 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
116 void 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
145 void 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
153 SpaceManagerStatistics::SpaceManagerStatistics() { reset(); }
154
155 void 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
162 void SpaceManagerStatistics::add_free_blocks_info(uintx num, size_t cap) {
163 _free_blocks_num += num;
164 _free_blocks_cap_words += cap;
165 }
166
167 void 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.
176 UsedChunksStatistics 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
184 void 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
220 ClassLoaderMetaspaceStatistics::ClassLoaderMetaspaceStatistics() { reset(); }
221
222 void 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
230 SpaceManagerStatistics 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
239 void 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
246 void 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
|
1 /*
2 * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
3 * Copyright (c) 2018, 2020 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
26 #include "precompiled.hpp"
27
28
29 #include "memory/metaspace/chunkLevel.hpp"
30 #include "memory/metaspace/metaspaceCommon.hpp"
31 #include "memory/metaspace/metaspaceStatistics.hpp"
32
33 #include "utilities/debug.hpp"
34 #include "utilities/globalDefinitions.hpp"
35 #include "utilities/ostream.hpp"
36
37 namespace metaspace {
38
39
40 // Returns total word size of all chunks in this manager.
41 void cm_stats_t::add(const cm_stats_t& other) {
42 for (chunklevel_t l = chunklevel::LOWEST_CHUNK_LEVEL; l <= chunklevel::HIGHEST_CHUNK_LEVEL; l ++) {
43 num_chunks[l] += other.num_chunks[l];
44 committed_word_size[l] += other.committed_word_size[l];
45 }
46 }
47
48 // Returns total word size of all chunks in this manager.
49 size_t cm_stats_t::total_word_size() const {
50 size_t s = 0;
51 for (chunklevel_t l = chunklevel::LOWEST_CHUNK_LEVEL; l <= chunklevel::HIGHEST_CHUNK_LEVEL; l ++) {
52 s += num_chunks[l] * chunklevel::word_size_for_level(l);
53 }
54 return s;
55 }
56
57 // Returns total committed word size of all chunks in this manager.
58 size_t cm_stats_t::total_committed_word_size() const {
59 size_t s = 0;
60 for (chunklevel_t l = chunklevel::LOWEST_CHUNK_LEVEL; l <= chunklevel::HIGHEST_CHUNK_LEVEL; l ++) {
61 s += committed_word_size[l];
62 }
63 return s;
64 }
65
66
67 void cm_stats_t::print_on(outputStream* st, size_t scale) const {
68 // Note: used as part of MetaspaceReport so formatting matters.
69 size_t total_size = 0;
70 size_t total_committed_size = 0;
71 for (chunklevel_t l = chunklevel::LOWEST_CHUNK_LEVEL; l <= chunklevel::HIGHEST_CHUNK_LEVEL; l ++) {
72 st->cr();
73 chunklevel::print_chunk_size(st, l);
74 st->print(": ");
75 if (num_chunks[l] > 0) {
76 const size_t word_size = num_chunks[l] * chunklevel::word_size_for_level(l);
77
78 st->print("%4d, capacity=", num_chunks[l]);
79 print_scaled_words(st, word_size, scale);
80
81 st->print(", committed=");
82 print_scaled_words_and_percentage(st, committed_word_size[l], word_size, scale);
83
84 total_size += word_size;
85 total_committed_size += committed_word_size[l];
86 } else {
87 st->print("(none)");
88 }
89 }
90 st->cr();
91 st->print("Total word size: ");
92 print_scaled_words(st, total_size, scale);
93 st->print(", committed: ");
94 print_scaled_words_and_percentage(st, total_committed_size, total_size, scale);
95 st->cr();
96 }
97
98 #ifdef ASSERT
99 void cm_stats_t::verify() const {
100 assert(total_committed_word_size() <= total_word_size(),
101 "Sanity");
102 }
103 #endif
104
105
106 void in_use_chunk_stats_t::print_on(outputStream* st, size_t scale) const {
107 int col = st->position();
108 st->print("%4d chunk%s, ", num, num != 1 ? "s" : "");
109 if (num > 0) {
110 col += 14; st->fill_to(col);
111
112 print_scaled_words(st, word_size, scale, 5);
113 st->print(" capacity,");
114
115 col += 20; st->fill_to(col);
116 print_scaled_words_and_percentage(st, committed_words, word_size, scale, 5);
117 st->print(" committed, ");
118
119 col += 18; st->fill_to(col);
120 print_scaled_words_and_percentage(st, used_words, word_size, scale, 5);
121 st->print(" used, ");
122
123 col += 20; st->fill_to(col);
124 print_scaled_words_and_percentage(st, free_words, word_size, scale, 5);
125 st->print(" free, ");
126
127 col += 20; st->fill_to(col);
128 print_scaled_words_and_percentage(st, waste_words, word_size, scale, 5);
129 st->print(" waste ");
130
131 }
132 }
133
134 #ifdef ASSERT
135 void in_use_chunk_stats_t::verify() const {
136 assert(word_size >= committed_words &&
137 committed_words == used_words + free_words + waste_words,
138 "Sanity: cap " SIZE_FORMAT ", committed " SIZE_FORMAT ", used " SIZE_FORMAT ", free " SIZE_FORMAT ", waste " SIZE_FORMAT ".",
139 word_size, committed_words, used_words, free_words, waste_words);
140 }
141 #endif
142
143 void arena_stats_t::add(const arena_stats_t& other) {
144 for (chunklevel_t l = chunklevel::LOWEST_CHUNK_LEVEL; l <= chunklevel::HIGHEST_CHUNK_LEVEL; l ++) {
145 stats[l].add(other.stats[l]);
146 }
147 free_blocks_num += other.free_blocks_num;
148 free_blocks_word_size += other.free_blocks_word_size;
149 }
150
151
152 // Returns total chunk statistics over all chunk types.
153 in_use_chunk_stats_t arena_stats_t::totals() const {
154 in_use_chunk_stats_t out;
155 for (chunklevel_t l = chunklevel::LOWEST_CHUNK_LEVEL; l <= chunklevel::HIGHEST_CHUNK_LEVEL; l ++) {
156 out.add(stats[l]);
157 }
158 return out;
159 }
160
161 void arena_stats_t::print_on(outputStream* st, size_t scale, bool detailed) const {
162 streamIndentor sti(st);
163 if (detailed) {
164 st->cr_indent();
165 st->print("Usage by chunk level:");
166 {
167 streamIndentor sti2(st);
168 for (chunklevel_t l = chunklevel::LOWEST_CHUNK_LEVEL; l <= chunklevel::HIGHEST_CHUNK_LEVEL; l ++) {
169 st->cr_indent();
170 chunklevel::print_chunk_size(st, l);
171 st->print(" chunks: ");
172 if (stats[l].num == 0) {
173 st->print(" (none)");
174 } else {
175 stats[l].print_on(st, scale);
176 }
177 }
178
179 st->cr_indent();
180 st->print("%15s: ", "-total-");
181 totals().print_on(st, scale);
182 }
183 if (free_blocks_num > 0) {
184 st->cr_indent();
185 st->print("deallocated: " UINTX_FORMAT " blocks with ", free_blocks_num);
186 print_scaled_words(st, free_blocks_word_size, scale);
187 }
188 } else {
189 totals().print_on(st, scale);
190 st->print(", ");
191 st->print("deallocated: " UINTX_FORMAT " blocks with ", free_blocks_num);
192 print_scaled_words(st, free_blocks_word_size, scale);
193 }
194 }
195
196 #ifdef ASSERT
197
198 void arena_stats_t::verify() const {
199 size_t total_used = 0;
200 for (chunklevel_t l = chunklevel::LOWEST_CHUNK_LEVEL; l <= chunklevel::HIGHEST_CHUNK_LEVEL; l ++) {
201 stats[l].verify();
202 total_used += stats[l].used_words;
203 }
204 // Deallocated allocations still count as used
205 assert(total_used >= free_blocks_word_size,
206 "Sanity");
207 }
208 #endif
209
210
211 // Returns total arena statistics for both class and non-class metaspace
212 arena_stats_t clms_stats_t::totals() const {
213 arena_stats_t out;
214 out.add(arena_stats_nonclass);
215 out.add(arena_stats_class);
216 return out;
217 }
218
219 void clms_stats_t::print_on(outputStream* st, size_t scale, bool detailed) const {
220 streamIndentor sti(st);
221 st->cr_indent();
222 if (Metaspace::using_class_space()) {
223 st->print("Non-Class: ");
224 }
225 arena_stats_nonclass.print_on(st, scale, detailed);
226 if (detailed) {
227 st->cr();
228 }
229 if (Metaspace::using_class_space()) {
230 st->cr_indent();
231 st->print(" Class: ");
232 arena_stats_class.print_on(st, scale, detailed);
233 if (detailed) {
234 st->cr();
235 }
236 st->cr_indent();
237 st->print(" Both: ");
238 totals().print_on(st, scale, detailed);
239 if (detailed) {
240 st->cr();
241 }
242 }
243 st->cr();
244 }
245
246
247 #ifdef ASSERT
248 void clms_stats_t::verify() const {
249 arena_stats_nonclass.verify();
250 arena_stats_class.verify();
251 }
252 #endif
253
254 } // end namespace metaspace
255
256
257
|