1 /* 2 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #ifndef SHARE_VM_SERVICES_MEM_BASELINE_HPP 26 #define SHARE_VM_SERVICES_MEM_BASELINE_HPP 27 28 #include "memory/allocation.hpp" 29 #include "runtime/mutex.hpp" 30 #include "services/memPtr.hpp" 31 #include "services/memSnapshot.hpp" 32 33 // compare unsigned number 34 #define UNSIGNED_COMPARE(a, b) ((a > b) ? 1 : ((a == b) ? 0 : -1)) 35 36 /* 37 * MallocCallsitePointer and VMCallsitePointer are used 38 * to baseline memory blocks with their callsite information. 39 * They are only available when detail tracking is turned 40 * on. 41 */ 42 43 /* baselined malloc record aggregated by callsite */ 44 class MallocCallsitePointer : public MemPointer { 45 private: 46 size_t _count; // number of malloc invocation from this callsite 47 size_t _amount; // total amount of memory malloc-ed from this callsite 48 49 public: 50 MallocCallsitePointer() { 51 _count = 0; 52 _amount = 0; 53 } 54 55 MallocCallsitePointer(address pc) : MemPointer(pc) { 56 _count = 0; 57 _amount = 0; 58 } 59 60 MallocCallsitePointer& operator=(const MallocCallsitePointer& p) { 61 MemPointer::operator=(p); 62 _count = p.count(); 63 _amount = p.amount(); 64 return *this; 65 } 66 67 inline void inc(size_t size) { 68 _count ++; 69 _amount += size; 70 }; 71 72 inline size_t count() const { 73 return _count; 74 } 75 76 inline size_t amount() const { 77 return _amount; 78 } 79 }; 80 81 // baselined virtual memory record aggregated by callsite 82 class VMCallsitePointer : public MemPointer { 83 private: 84 size_t _count; // number of invocation from this callsite 85 size_t _reserved_amount; // total reserved amount 86 size_t _committed_amount; // total committed amount 87 88 public: 89 VMCallsitePointer() { 90 _count = 0; 91 _reserved_amount = 0; 92 _committed_amount = 0; 93 } 94 95 VMCallsitePointer(address pc) : MemPointer(pc) { 96 _count = 0; 97 _reserved_amount = 0; 98 _committed_amount = 0; 99 } 100 101 VMCallsitePointer& operator=(const VMCallsitePointer& p) { 102 MemPointer::operator=(p); 103 _count = p.count(); 104 _reserved_amount = p.reserved_amount(); 105 _committed_amount = p.committed_amount(); 106 return *this; 107 } 108 109 inline void inc(size_t reserved, size_t committed) { 110 _count ++; 111 _reserved_amount += reserved; 112 _committed_amount += committed; 113 } 114 115 inline size_t count() const { 116 return _count; 117 } 118 119 inline size_t reserved_amount() const { 120 return _reserved_amount; 121 } 122 123 inline size_t committed_amount() const { 124 return _committed_amount; 125 } 126 }; 127 128 // maps a memory type flag to readable name 129 typedef struct _memType2Name { 130 MEMFLAGS _flag; 131 const char* _name; 132 } MemType2Name; 133 134 135 // This class aggregates malloc'd records by memory type 136 class MallocMem : public _ValueObj { 137 private: 138 MEMFLAGS _type; 139 140 size_t _count; 141 size_t _amount; 142 143 public: 144 MallocMem() { 145 _type = mtNone; 146 _count = 0; 147 _amount = 0; 148 } 149 150 MallocMem(MEMFLAGS flags) { 151 assert(HAS_VALID_MEMORY_TYPE(flags), "no type"); 152 _type = FLAGS_TO_MEMORY_TYPE(flags); 153 _count = 0; 154 _amount = 0; 155 } 156 157 inline void set_type(MEMFLAGS flag) { 158 _type = flag; 159 } 160 161 inline void clear() { 162 _count = 0; 163 _amount = 0; 164 _type = mtNone; 165 } 166 167 MallocMem& operator=(const MallocMem& m) { 168 assert(_type == m.type(), "different type"); 169 _count = m.count(); 170 _amount = m.amount(); 171 return *this; 172 } 173 174 inline void inc(size_t amt) { 175 _amount += amt; 176 _count ++; 177 } 178 179 inline void reduce(size_t amt) { 180 assert(_amount >= amt, "Just check"); 181 _amount -= amt; 182 } 183 184 inline void overwrite_counter(size_t count) { 185 _count = count; 186 } 187 188 inline MEMFLAGS type() const { 189 return _type; 190 } 191 192 inline bool is_type(MEMFLAGS flags) const { 193 return FLAGS_TO_MEMORY_TYPE(flags) == _type; 194 } 195 196 inline size_t count() const { 197 return _count; 198 } 199 200 inline size_t amount() const { 201 return _amount; 202 } 203 }; 204 205 // This class records live arena's memory usage 206 class ArenaMem : public MallocMem { 207 public: 208 ArenaMem(MEMFLAGS typeflag): MallocMem(typeflag) { 209 } 210 ArenaMem() { } 211 }; 212 213 // This class aggregates virtual memory by its memory type 214 class VMMem : public _ValueObj { 215 private: 216 MEMFLAGS _type; 217 218 size_t _count; 219 size_t _reserved_amount; 220 size_t _committed_amount; 221 222 public: 223 VMMem() { 224 _type = mtNone; 225 _count = 0; 226 _reserved_amount = 0; 227 _committed_amount = 0; 228 } 229 230 VMMem(MEMFLAGS flags) { 231 assert(HAS_VALID_MEMORY_TYPE(flags), "no type"); 232 _type = FLAGS_TO_MEMORY_TYPE(flags); 233 _count = 0; 234 _reserved_amount = 0; 235 _committed_amount = 0; 236 } 237 238 inline void clear() { 239 _type = mtNone; 240 _count = 0; 241 _reserved_amount = 0; 242 _committed_amount = 0; 243 } 244 245 inline void set_type(MEMFLAGS flags) { 246 _type = FLAGS_TO_MEMORY_TYPE(flags); 247 } 248 249 VMMem& operator=(const VMMem& m) { 250 assert(_type == m.type(), "different type"); 251 252 _count = m.count(); 253 _reserved_amount = m.reserved_amount(); 254 _committed_amount = m.committed_amount(); 255 return *this; 256 } 257 258 259 inline MEMFLAGS type() const { 260 return _type; 261 } 262 263 inline bool is_type(MEMFLAGS flags) const { 264 return FLAGS_TO_MEMORY_TYPE(flags) == _type; 265 } 266 267 inline void inc(size_t reserved_amt, size_t committed_amt) { 268 _reserved_amount += reserved_amt; 269 _committed_amount += committed_amt; 270 _count ++; 271 } 272 273 inline size_t count() const { 274 return _count; 275 } 276 277 inline size_t reserved_amount() const { 278 return _reserved_amount; 279 } 280 281 inline size_t committed_amount() const { 282 return _committed_amount; 283 } 284 }; 285 286 287 288 #define NUMBER_OF_MEMORY_TYPE (mt_number_of_types + 1) 289 290 class BaselineReporter; 291 class BaselineComparisonReporter; 292 293 /* 294 * This class baselines current memory snapshot. 295 * A memory baseline summarizes memory usage by memory type, 296 * aggregates memory usage by callsites when detail tracking 297 * is on. 298 */ 299 class MemBaseline : public _ValueObj { 300 friend class BaselineReporter; 301 friend class BaselineComparisonReporter; 302 303 private: 304 // overall summaries 305 size_t _total_malloced; 306 size_t _total_vm_reserved; 307 size_t _total_vm_committed; 308 size_t _number_of_classes; 309 size_t _number_of_threads; 310 311 // if it has properly baselined 312 bool _baselined; 313 314 // we categorize memory into three categories within the memory type 315 MallocMem _malloc_data[NUMBER_OF_MEMORY_TYPE]; 316 VMMem _vm_data[NUMBER_OF_MEMORY_TYPE]; 317 ArenaMem _arena_data[NUMBER_OF_MEMORY_TYPE]; 318 319 // memory records that aggregate memory usage by callsites. 320 // only available when detail tracking is on. 321 MemPointerArray* _malloc_cs; 322 MemPointerArray* _vm_cs; 323 // virtual memory map 324 MemPointerArray* _vm_map; 325 326 private: 327 static MemType2Name MemType2NameMap[NUMBER_OF_MEMORY_TYPE]; 328 329 private: 330 // should not use copy constructor 331 MemBaseline(MemBaseline& copy) { ShouldNotReachHere(); } 332 333 public: 334 // create a memory baseline 335 MemBaseline(); 336 337 virtual ~MemBaseline(); 338 339 inline bool baselined() const { 340 return _baselined; 341 } 342 343 MemBaseline& operator=(const MemBaseline& other); 344 345 // reset the baseline for reuse 346 void clear(); 347 348 // baseline the snapshot 349 bool baseline(MemSnapshot& snapshot, bool summary_only = true); 350 351 bool baseline(const MemPointerArray* malloc_records, 352 const MemPointerArray* vm_records, 353 bool summary_only = true); 354 355 // total malloc'd memory of specified memory type 356 inline size_t malloc_amount(MEMFLAGS flag) const { 357 return _malloc_data[flag2index(flag)].amount(); 358 } 359 // number of malloc'd memory blocks of specified memory type 360 inline size_t malloc_count(MEMFLAGS flag) const { 361 return _malloc_data[flag2index(flag)].count(); 362 } 363 // total memory used by arenas of specified memory type 364 inline size_t arena_amount(MEMFLAGS flag) const { 365 return _arena_data[flag2index(flag)].amount(); 366 } 367 // number of arenas of specified memory type 368 inline size_t arena_count(MEMFLAGS flag) const { 369 return _arena_data[flag2index(flag)].count(); 370 } 371 // total reserved memory of specified memory type 372 inline size_t reserved_amount(MEMFLAGS flag) const { 373 return _vm_data[flag2index(flag)].reserved_amount(); 374 } 375 // total committed memory of specified memory type 376 inline size_t committed_amount(MEMFLAGS flag) const { 377 return _vm_data[flag2index(flag)].committed_amount(); 378 } 379 // total memory (malloc'd + mmap'd + arena) of specified 380 // memory type 381 inline size_t total_amount(MEMFLAGS flag) const { 382 int index = flag2index(flag); 383 return _malloc_data[index].amount() + 384 _vm_data[index].reserved_amount() + 385 _arena_data[index].amount(); 386 } 387 388 /* overall summaries */ 389 390 // total malloc'd memory in snapshot 391 inline size_t total_malloc_amount() const { 392 return _total_malloced; 393 } 394 // total mmap'd memory in snapshot 395 inline size_t total_reserved_amount() const { 396 return _total_vm_reserved; 397 } 398 // total committed memory in snapshot 399 inline size_t total_committed_amount() const { 400 return _total_vm_committed; 401 } 402 // number of loaded classes 403 inline size_t number_of_classes() const { 404 return _number_of_classes; 405 } 406 // number of running threads 407 inline size_t number_of_threads() const { 408 return _number_of_threads; 409 } 410 // lookup human readable name of a memory type 411 static const char* type2name(MEMFLAGS type); 412 413 private: 414 // convert memory flag to the index to mapping table 415 int flag2index(MEMFLAGS flag) const; 416 417 // reset baseline values 418 void reset(); 419 420 // summarize the records in global snapshot 421 bool baseline_malloc_summary(const MemPointerArray* malloc_records); 422 bool baseline_vm_summary(const MemPointerArray* vm_records); 423 bool baseline_malloc_details(const MemPointerArray* malloc_records); 424 bool baseline_vm_details(const MemPointerArray* vm_records); 425 426 // print a line of malloc'd memory aggregated by callsite 427 void print_malloc_callsite(outputStream* st, address pc, size_t size, 428 size_t count, int diff_amt, int diff_count) const; 429 // print a line of mmap'd memory aggregated by callsite 430 void print_vm_callsite(outputStream* st, address pc, size_t rsz, 431 size_t csz, int diff_rsz, int diff_csz) const; 432 433 // sorting functions for raw records 434 static int malloc_sort_by_pc(const void* p1, const void* p2); 435 static int malloc_sort_by_addr(const void* p1, const void* p2); 436 437 private: 438 // sorting functions for baselined records 439 static int bl_malloc_sort_by_size(const void* p1, const void* p2); 440 static int bl_vm_sort_by_size(const void* p1, const void* p2); 441 static int bl_malloc_sort_by_pc(const void* p1, const void* p2); 442 static int bl_vm_sort_by_pc(const void* p1, const void* p2); 443 }; 444 445 446 #endif // SHARE_VM_SERVICES_MEM_BASELINE_HPP