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 28 #include "memory/metaspace/chunkLevel.hpp" 29 #include "memory/metaspace/metaspaceCommon.hpp" 30 #include "memory/metaspace/metaspaceStatistics.hpp" 31 32 #include "utilities/debug.hpp" 33 #include "utilities/globalDefinitions.hpp" 34 #include "utilities/ostream.hpp" 35 36 namespace metaspace { 37 38 // ChunkManagerStatistics methods 39 40 ChunkManagerStatistics::ChunkManagerStatistics() { 41 for (chklvl_t l = chklvl::LOWEST_CHUNK_LEVEL; l <= chklvl::HIGHEST_CHUNK_LEVEL; l ++) { 42 num_chunks[l] = 0; 43 committed_word_size[l] = 0; 44 } 45 } 46 47 size_t ChunkManagerStatistics::total_capacity() const { 48 size_t cap = 0; 49 for (chklvl_t l = chklvl::LOWEST_CHUNK_LEVEL; l <= chklvl::HIGHEST_CHUNK_LEVEL; l ++) { 50 cap += num_chunks[l] * chklvl::word_size_for_level(l); 51 } 52 return cap; 53 } 54 55 void ChunkManagerStatistics::print_on(outputStream* st, size_t scale) const { 56 size_t total_size = 0; 57 size_t total_committed_size = 0; 58 for (chklvl_t l = chklvl::LOWEST_CHUNK_LEVEL; l <= chklvl::HIGHEST_CHUNK_LEVEL; l ++) { 59 st->cr(); 60 st->print(SIZE_FORMAT "K chunks: ", (chklvl::word_size_for_level(l) * BytesPerWord) / K); 61 if (num_chunks[l] > 0) { 62 const size_t word_size = num_chunks[l] * chklvl::word_size_for_level(l); 63 64 st->print("%4d, capacity=", num_chunks[l]); 65 print_scaled_words(st, word_size, scale); 66 67 st->print(", committed="); 68 print_scaled_words_and_percentage(st, committed_word_size[l], word_size, scale); 69 70 total_size += word_size; 71 total_committed_size += committed_word_size[l]; 72 } else { 73 st->print("(none)"); 74 } 75 } 76 st->cr(); 77 st->print("Total capacity: "); 78 print_scaled_words(st, total_size, scale); 79 st->print(", committed: "); 80 print_scaled_words_and_percentage(st, total_committed_size, total_size, scale); 81 st->cr(); 82 } 83 84 // UsedChunksStatistics methods 85 86 void UsedChunksStatistics::print_on(outputStream* st, size_t scale) const { 87 int col = st->position(); 88 st->print("%4d chunk%s, ", num, num != 1 ? "s" : ""); 89 if (num > 0) { 90 col += 14; st->fill_to(col); 91 92 print_scaled_words(st, cap, scale, 5); 93 st->print(" capacity, "); 94 95 col += 18; st->fill_to(col); 96 print_scaled_words_and_percentage(st, used, cap, scale, 5); 97 st->print(" used, "); 98 99 col += 20; st->fill_to(col); 100 print_scaled_words_and_percentage(st, free, cap, scale, 5); 101 st->print(" free, "); 102 103 col += 20; st->fill_to(col); 104 print_scaled_words_and_percentage(st, waste, cap, scale, 5); 105 st->print(" waste "); 106 107 } 108 DEBUG_ONLY(check_sanity()); 109 } 110 111 #ifdef ASSERT 112 void UsedChunksStatistics::check_sanity() const { 113 assert(cap == used + free + waste, "Sanity: Capacity."); 114 } 115 #endif 116 117 // SpaceManagerStatistics methods 118 119 void SpaceManagerStatistics::add(const SpaceManagerStatistics& other) { 120 for (chklvl_t l = chklvl::LOWEST_CHUNK_LEVEL; l <= chklvl::HIGHEST_CHUNK_LEVEL; l ++) { 121 chunk_stats[l].add(other.chunk_stats[l]); 122 } 123 free_blocks_num += other.free_blocks_num; 124 free_blocks_word_size += other.free_blocks_word_size; 125 } 126 127 // Returns total chunk statistics over all chunk types. 128 UsedChunksStatistics SpaceManagerStatistics::totals() const { 129 UsedChunksStatistics stat; 130 for (chklvl_t l = chklvl::LOWEST_CHUNK_LEVEL; l <= chklvl::HIGHEST_CHUNK_LEVEL; l ++) { 131 stat.add(chunk_stats[l]); 132 } 133 return stat; 134 } 135 136 void SpaceManagerStatistics::print_on(outputStream* st, size_t scale, bool detailed) const { 137 streamIndentor sti(st); 138 if (detailed) { 139 st->cr_indent(); 140 st->print("Usage by chunk level:"); 141 { 142 streamIndentor sti2(st); 143 for (chklvl_t l = chklvl::LOWEST_CHUNK_LEVEL; l <= chklvl::HIGHEST_CHUNK_LEVEL; l ++) { 144 st->cr_indent(); 145 st->print(SIZE_FORMAT "k chunks: ", (chklvl::word_size_for_level(l) * BytesPerWord) / K); 146 if (chunk_stats[l].num == 0) { 147 st->print(" (none)"); 148 } else { 149 chunk_stats[l].print_on(st, scale); 150 } 151 } 152 153 st->cr_indent(); 154 st->print("%15s: ", "-total-"); 155 totals().print_on(st, scale); 156 } 157 if (free_blocks_num > 0) { 158 st->cr_indent(); 159 st->print("deallocated: " UINTX_FORMAT " blocks with ", free_blocks_num); 160 print_scaled_words(st, free_blocks_word_size, scale); 161 } 162 } else { 163 totals().print_on(st, scale); 164 st->print(", "); 165 st->print("deallocated: " UINTX_FORMAT " blocks with ", free_blocks_num); 166 print_scaled_words(st, free_blocks_word_size, scale); 167 } 168 } 169 170 // ClassLoaderMetaspaceStatistics methods 171 172 // Returns total space manager statistics for both class and non-class metaspace 173 SpaceManagerStatistics ClassLoaderMetaspaceStatistics::totals() const { 174 SpaceManagerStatistics stats; 175 stats.add(sm_stats[ClassType]); 176 stats.add(sm_stats[NonClassType]); 177 return stats; 178 } 179 180 void ClassLoaderMetaspaceStatistics::print_on(outputStream* st, size_t scale, bool detailed) const { 181 streamIndentor sti(st); 182 st->cr_indent(); 183 if (Metaspace::using_class_space()) { 184 st->print("Non-Class: "); 185 } 186 sm_stats[NonClassType].print_on(st, scale, detailed); 187 if (detailed) { 188 st->cr(); 189 } 190 if (Metaspace::using_class_space()) { 191 st->cr_indent(); 192 st->print(" Class: "); 193 sm_stats[ClassType].print_on(st, scale, detailed); 194 if (detailed) { 195 st->cr(); 196 } 197 st->cr_indent(); 198 st->print(" Both: "); 199 totals().print_on(st, scale, detailed); 200 if (detailed) { 201 st->cr(); 202 } 203 } 204 st->cr(); 205 } 206 207 } // end namespace metaspace 208 209 210