1 /*
  2  * Copyright (c) 2018, 2021, 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 #include "memory/metaspace/freeBlocks.hpp"

 28 #include "memory/metaspace/metaspaceCommon.hpp"
 29 #include "memory/metaspace/metaspaceSettings.hpp"
 30 #include "memory/metaspace/virtualSpaceNode.hpp"
 31 #include "utilities/align.hpp"
 32 #include "utilities/debug.hpp"
 33 #include "utilities/globalDefinitions.hpp"
 34 #include "utilities/ostream.hpp"
 35 
 36 namespace metaspace {
 37 
 38 // Print a size, in words, scaled.
 39 void print_scaled_words(outputStream* st, size_t word_size, size_t scale, int width) {
 40   print_human_readable_size(st, word_size * sizeof(MetaWord), scale, width);
 41 }
 42 
 43 // Convenience helper: prints a size value and a percentage.
 44 void print_scaled_words_and_percentage(outputStream* st, size_t word_size, size_t compare_word_size, size_t scale, int width) {
 45   print_scaled_words(st, word_size, scale, width);
 46   st->print(" (");
 47   print_percentage(st, compare_word_size, word_size);
 48   st->print(")");
 49 }
 50 
 51 static const char* display_unit_for_scale(size_t scale) {
 52   const char* s = NULL;
 53   switch(scale) {
 54     case 1: s = "bytes"; break;
 55     case BytesPerWord: s = "words"; break;
 56     case K: s = "KB"; break;
 57     case M: s = "MB"; break;
 58     case G: s = "GB"; break;
 59     default:
 60       ShouldNotReachHere();
 61   }
 62   return s;
 63 }
 64 
 65 // Print a human readable size.
 66 // byte_size: size, in bytes, to be printed.
 67 // scale: one of 1 (byte-wise printing), sizeof(word) (word-size printing), K, M, G (scaled by KB, MB, GB respectively,
 68 //         or 0, which means the best scale is chosen dynamically.
 69 // width: printing width.
 70 void print_human_readable_size(outputStream* st, size_t byte_size, size_t scale, int width)  {
 71   if (scale == 0) {
 72     // Dynamic mode. Choose scale for this value.
 73     if (byte_size == 0) {
 74       // Zero values are printed as bytes.
 75       scale = 1;
 76     } else {
 77       if (byte_size >= G) {
 78         scale = G;
 79       } else if (byte_size >= M) {
 80         scale = M;
 81       } else if (byte_size >= K) {
 82         scale = K;
 83       } else {
 84         scale = 1;
 85       }
 86     }
 87     return print_human_readable_size(st, byte_size, scale, width);
 88   }
 89 
 90 #ifdef ASSERT
 91   assert(scale == 1 || scale == BytesPerWord ||
 92          scale == K || scale == M || scale == G, "Invalid scale");
 93   // Special case: printing wordsize should only be done with word-sized values
 94   if (scale == BytesPerWord) {
 95     assert(byte_size % BytesPerWord == 0, "not word sized");
 96   }
 97 #endif
 98 
 99   if (width == -1) {
100     if (scale == 1) {
101       st->print(SIZE_FORMAT " bytes", byte_size);
102     } else if (scale == BytesPerWord) {
103       st->print(SIZE_FORMAT " words", byte_size / BytesPerWord);
104     } else {
105       const char* display_unit = display_unit_for_scale(scale);
106       float display_value = (float) byte_size / scale;
107       // Prevent very small but non-null values showing up as 0.00.
108       if (byte_size > 0 && display_value < 0.01f) {
109         st->print("<0.01 %s", display_unit);
110       } else {
111         st->print("%.2f %s", display_value, display_unit);
112       }
113     }
114   } else {
115     if (scale == 1) {
116       st->print("%*" PRIuPTR " bytes", width, byte_size);
117     } else if (scale == BytesPerWord) {
118       st->print("%*" PRIuPTR " words", width, byte_size / BytesPerWord);
119     } else {
120       const char* display_unit = display_unit_for_scale(scale);
121       float display_value = (float) byte_size / scale;
122       // Since we use width to display a number with two trailing digits, increase it a bit.
123       width += 3;
124       // Prevent very small but non-null values showing up as 0.00.
125       if (byte_size > 0 && display_value < 0.01f) {
126         st->print("%*s %s", width, "<0.01", display_unit);
127       } else {
128         st->print("%*.2f %s", width, display_value, display_unit);
129       }
130     }
131   }
132 }
133 
134 // Prints a percentage value. Values smaller than 1% but not 0 are displayed as "<1%", values
135 // larger than 99% but not 100% are displayed as ">100%".
136 void print_percentage(outputStream* st, size_t total, size_t part) {
137   if (total == 0) {
138     st->print("  ?%%");
139   } else if (part == 0) {
140     st->print("  0%%");
141   } else if (part == total) {
142     st->print("100%%");
143   } else {
144     // Note: clearly print very-small-but-not-0% and very-large-but-not-100% percentages.
145     float p = ((float)part / total) * 100.0f;
146     if (p < 1.0f) {
147       st->print(" <1%%");
148     } else if (p > 99.0f){
149       st->print(">99%%");
150     } else {
151       st->print("%3.0f%%", p);
152     }
153   }
154 }
155 
156 const char* loaders_plural(uintx num) {
157   return num == 1 ? "loader" : "loaders";
158 }
159 
160 const char* classes_plural(uintx num) {
161   return num == 1 ? "class" : "classes";
162 }
163 
164 void print_number_of_classes(outputStream* out, uintx classes, uintx classes_shared) {
165   out->print(UINTX_FORMAT " %s", classes, classes_plural(classes));
166   if (classes_shared > 0) {
167     out->print(" (" UINTX_FORMAT " shared)", classes_shared);
168   }
169 }
170 
171 // Given a net allocation word size, return the raw word size we actually allocate.
172 // Note: externally visible for gtests.
173 //static
174 size_t get_raw_word_size_for_requested_word_size(size_t word_size) {
175   size_t byte_size = word_size * BytesPerWord;
176 
177   // Deallocated metablocks are kept in a binlist which limits their minimal
178   //  size to at least the size of a binlist item (2 words).
179   byte_size = MAX2(byte_size, FreeBlocks::MinWordSize * BytesPerWord);
180 
181   // Metaspace allocations are aligned to word size.
182   byte_size = align_up(byte_size, AllocationAlignmentByteSize);
183 
184   size_t raw_word_size = byte_size / BytesPerWord;
185   assert(raw_word_size * BytesPerWord == byte_size, "Sanity");
186   return raw_word_size;
187 }
188 
189 } // namespace metaspace
190 
--- EOF ---