1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/services/memBaseline.hpp Thu Jun 28 17:03:16 2012 -0400 1.3 @@ -0,0 +1,447 @@ 1.4 +/* 1.5 + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.23 + * or visit www.oracle.com if you need additional information or have any 1.24 + * questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +#ifndef SHARE_VM_SERVICES_MEM_BASELINE_HPP 1.29 +#define SHARE_VM_SERVICES_MEM_BASELINE_HPP 1.30 + 1.31 +#include "memory/allocation.hpp" 1.32 +#include "runtime/mutex.hpp" 1.33 +#include "services/memPtr.hpp" 1.34 +#include "services/memSnapshot.hpp" 1.35 + 1.36 +// compare unsigned number 1.37 +#define UNSIGNED_COMPARE(a, b) ((a > b) ? 1 : ((a == b) ? 0 : -1)) 1.38 + 1.39 +/* 1.40 + * MallocCallsitePointer and VMCallsitePointer are used 1.41 + * to baseline memory blocks with their callsite information. 1.42 + * They are only available when detail tracking is turned 1.43 + * on. 1.44 + */ 1.45 + 1.46 +/* baselined malloc record aggregated by callsite */ 1.47 +class MallocCallsitePointer : public MemPointer { 1.48 + private: 1.49 + size_t _count; // number of malloc invocation from this callsite 1.50 + size_t _amount; // total amount of memory malloc-ed from this callsite 1.51 + 1.52 + public: 1.53 + MallocCallsitePointer() { 1.54 + _count = 0; 1.55 + _amount = 0; 1.56 + } 1.57 + 1.58 + MallocCallsitePointer(address pc) : MemPointer(pc) { 1.59 + _count = 0; 1.60 + _amount = 0; 1.61 + } 1.62 + 1.63 + MallocCallsitePointer& operator=(const MallocCallsitePointer& p) { 1.64 + MemPointer::operator=(p); 1.65 + _count = p.count(); 1.66 + _amount = p.amount(); 1.67 + return *this; 1.68 + } 1.69 + 1.70 + inline void inc(size_t size) { 1.71 + _count ++; 1.72 + _amount += size; 1.73 + }; 1.74 + 1.75 + inline size_t count() const { 1.76 + return _count; 1.77 + } 1.78 + 1.79 + inline size_t amount() const { 1.80 + return _amount; 1.81 + } 1.82 +}; 1.83 + 1.84 +// baselined virtual memory record aggregated by callsite 1.85 +class VMCallsitePointer : public MemPointer { 1.86 + private: 1.87 + size_t _count; // number of invocation from this callsite 1.88 + size_t _reserved_amount; // total reserved amount 1.89 + size_t _committed_amount; // total committed amount 1.90 + 1.91 + public: 1.92 + VMCallsitePointer() { 1.93 + _count = 0; 1.94 + _reserved_amount = 0; 1.95 + _committed_amount = 0; 1.96 + } 1.97 + 1.98 + VMCallsitePointer(address pc) : MemPointer(pc) { 1.99 + _count = 0; 1.100 + _reserved_amount = 0; 1.101 + _committed_amount = 0; 1.102 + } 1.103 + 1.104 + VMCallsitePointer& operator=(const VMCallsitePointer& p) { 1.105 + MemPointer::operator=(p); 1.106 + _count = p.count(); 1.107 + _reserved_amount = p.reserved_amount(); 1.108 + _committed_amount = p.committed_amount(); 1.109 + return *this; 1.110 + } 1.111 + 1.112 + inline void inc(size_t reserved, size_t committed) { 1.113 + _count ++; 1.114 + _reserved_amount += reserved; 1.115 + _committed_amount += committed; 1.116 + } 1.117 + 1.118 + inline size_t count() const { 1.119 + return _count; 1.120 + } 1.121 + 1.122 + inline size_t reserved_amount() const { 1.123 + return _reserved_amount; 1.124 + } 1.125 + 1.126 + inline size_t committed_amount() const { 1.127 + return _committed_amount; 1.128 + } 1.129 +}; 1.130 + 1.131 +// maps a memory type flag to readable name 1.132 +typedef struct _memType2Name { 1.133 + MEMFLAGS _flag; 1.134 + const char* _name; 1.135 +} MemType2Name; 1.136 + 1.137 + 1.138 +// This class aggregates malloc'd records by memory type 1.139 +class MallocMem : public _ValueObj { 1.140 + private: 1.141 + MEMFLAGS _type; 1.142 + 1.143 + size_t _count; 1.144 + size_t _amount; 1.145 + 1.146 + public: 1.147 + MallocMem() { 1.148 + _type = mtNone; 1.149 + _count = 0; 1.150 + _amount = 0; 1.151 + } 1.152 + 1.153 + MallocMem(MEMFLAGS flags) { 1.154 + assert(HAS_VALID_MEMORY_TYPE(flags), "no type"); 1.155 + _type = FLAGS_TO_MEMORY_TYPE(flags); 1.156 + _count = 0; 1.157 + _amount = 0; 1.158 + } 1.159 + 1.160 + inline void set_type(MEMFLAGS flag) { 1.161 + _type = flag; 1.162 + } 1.163 + 1.164 + inline void clear() { 1.165 + _count = 0; 1.166 + _amount = 0; 1.167 + _type = mtNone; 1.168 + } 1.169 + 1.170 + MallocMem& operator=(const MallocMem& m) { 1.171 + assert(_type == m.type(), "different type"); 1.172 + _count = m.count(); 1.173 + _amount = m.amount(); 1.174 + return *this; 1.175 + } 1.176 + 1.177 + inline void inc(size_t amt) { 1.178 + _amount += amt; 1.179 + _count ++; 1.180 + } 1.181 + 1.182 + inline void reduce(size_t amt) { 1.183 + assert(_amount >= amt, "Just check"); 1.184 + _amount -= amt; 1.185 + } 1.186 + 1.187 + inline void overwrite_counter(size_t count) { 1.188 + _count = count; 1.189 + } 1.190 + 1.191 + inline MEMFLAGS type() const { 1.192 + return _type; 1.193 + } 1.194 + 1.195 + inline bool is_type(MEMFLAGS flags) const { 1.196 + return FLAGS_TO_MEMORY_TYPE(flags) == _type; 1.197 + } 1.198 + 1.199 + inline size_t count() const { 1.200 + return _count; 1.201 + } 1.202 + 1.203 + inline size_t amount() const { 1.204 + return _amount; 1.205 + } 1.206 +}; 1.207 + 1.208 +// This class records live arena's memory usage 1.209 +class ArenaMem : public MallocMem { 1.210 + public: 1.211 + ArenaMem(MEMFLAGS typeflag): MallocMem(typeflag) { 1.212 + } 1.213 + ArenaMem() { } 1.214 +}; 1.215 + 1.216 +// This class aggregates virtual memory by its memory type 1.217 +class VMMem : public _ValueObj { 1.218 + private: 1.219 + MEMFLAGS _type; 1.220 + 1.221 + size_t _count; 1.222 + size_t _reserved_amount; 1.223 + size_t _committed_amount; 1.224 + 1.225 + public: 1.226 + VMMem() { 1.227 + _type = mtNone; 1.228 + _count = 0; 1.229 + _reserved_amount = 0; 1.230 + _committed_amount = 0; 1.231 + } 1.232 + 1.233 + VMMem(MEMFLAGS flags) { 1.234 + assert(HAS_VALID_MEMORY_TYPE(flags), "no type"); 1.235 + _type = FLAGS_TO_MEMORY_TYPE(flags); 1.236 + _count = 0; 1.237 + _reserved_amount = 0; 1.238 + _committed_amount = 0; 1.239 + } 1.240 + 1.241 + inline void clear() { 1.242 + _type = mtNone; 1.243 + _count = 0; 1.244 + _reserved_amount = 0; 1.245 + _committed_amount = 0; 1.246 + } 1.247 + 1.248 + inline void set_type(MEMFLAGS flags) { 1.249 + _type = FLAGS_TO_MEMORY_TYPE(flags); 1.250 + } 1.251 + 1.252 + VMMem& operator=(const VMMem& m) { 1.253 + assert(_type == m.type(), "different type"); 1.254 + 1.255 + _count = m.count(); 1.256 + _reserved_amount = m.reserved_amount(); 1.257 + _committed_amount = m.committed_amount(); 1.258 + return *this; 1.259 + } 1.260 + 1.261 + 1.262 + inline MEMFLAGS type() const { 1.263 + return _type; 1.264 + } 1.265 + 1.266 + inline bool is_type(MEMFLAGS flags) const { 1.267 + return FLAGS_TO_MEMORY_TYPE(flags) == _type; 1.268 + } 1.269 + 1.270 + inline void inc(size_t reserved_amt, size_t committed_amt) { 1.271 + _reserved_amount += reserved_amt; 1.272 + _committed_amount += committed_amt; 1.273 + _count ++; 1.274 + } 1.275 + 1.276 + inline size_t count() const { 1.277 + return _count; 1.278 + } 1.279 + 1.280 + inline size_t reserved_amount() const { 1.281 + return _reserved_amount; 1.282 + } 1.283 + 1.284 + inline size_t committed_amount() const { 1.285 + return _committed_amount; 1.286 + } 1.287 +}; 1.288 + 1.289 + 1.290 + 1.291 +#define NUMBER_OF_MEMORY_TYPE (mt_number_of_types + 1) 1.292 + 1.293 +class BaselineReporter; 1.294 +class BaselineComparisonReporter; 1.295 + 1.296 +/* 1.297 + * This class baselines current memory snapshot. 1.298 + * A memory baseline summarizes memory usage by memory type, 1.299 + * aggregates memory usage by callsites when detail tracking 1.300 + * is on. 1.301 + */ 1.302 +class MemBaseline : public _ValueObj { 1.303 + friend class BaselineReporter; 1.304 + friend class BaselineComparisonReporter; 1.305 + 1.306 + private: 1.307 + // overall summaries 1.308 + size_t _total_malloced; 1.309 + size_t _total_vm_reserved; 1.310 + size_t _total_vm_committed; 1.311 + size_t _number_of_classes; 1.312 + size_t _number_of_threads; 1.313 + 1.314 + // if it has properly baselined 1.315 + bool _baselined; 1.316 + 1.317 + // we categorize memory into three categories within the memory type 1.318 + MallocMem _malloc_data[NUMBER_OF_MEMORY_TYPE]; 1.319 + VMMem _vm_data[NUMBER_OF_MEMORY_TYPE]; 1.320 + ArenaMem _arena_data[NUMBER_OF_MEMORY_TYPE]; 1.321 + 1.322 + // memory records that aggregate memory usage by callsites. 1.323 + // only available when detail tracking is on. 1.324 + MemPointerArray* _malloc_cs; 1.325 + MemPointerArray* _vm_cs; 1.326 + 1.327 + private: 1.328 + static MemType2Name MemType2NameMap[NUMBER_OF_MEMORY_TYPE]; 1.329 + 1.330 + private: 1.331 + // should not use copy constructor 1.332 + MemBaseline(MemBaseline& copy) { ShouldNotReachHere(); } 1.333 + 1.334 + public: 1.335 + // create a memory baseline 1.336 + MemBaseline(); 1.337 + 1.338 + virtual ~MemBaseline(); 1.339 + 1.340 + inline bool baselined() const { 1.341 + return _baselined; 1.342 + } 1.343 + 1.344 + MemBaseline& operator=(const MemBaseline& other); 1.345 + 1.346 + // reset the baseline for reuse 1.347 + void clear(); 1.348 + 1.349 + // baseline the snapshot 1.350 + bool baseline(MemSnapshot& snapshot, bool summary_only = true); 1.351 + 1.352 + bool baseline(const MemPointerArray* malloc_records, 1.353 + const MemPointerArray* vm_records, 1.354 + bool summary_only = true); 1.355 + 1.356 + // total malloc'd memory of specified memory type 1.357 + inline size_t malloc_amount(MEMFLAGS flag) const { 1.358 + return _malloc_data[flag2index(flag)].amount(); 1.359 + } 1.360 + // number of malloc'd memory blocks of specified memory type 1.361 + inline size_t malloc_count(MEMFLAGS flag) const { 1.362 + return _malloc_data[flag2index(flag)].count(); 1.363 + } 1.364 + // total memory used by arenas of specified memory type 1.365 + inline size_t arena_amount(MEMFLAGS flag) const { 1.366 + return _arena_data[flag2index(flag)].amount(); 1.367 + } 1.368 + // number of arenas of specified memory type 1.369 + inline size_t arena_count(MEMFLAGS flag) const { 1.370 + return _arena_data[flag2index(flag)].count(); 1.371 + } 1.372 + // total reserved memory of specified memory type 1.373 + inline size_t reserved_amount(MEMFLAGS flag) const { 1.374 + return _vm_data[flag2index(flag)].reserved_amount(); 1.375 + } 1.376 + // total committed memory of specified memory type 1.377 + inline size_t committed_amount(MEMFLAGS flag) const { 1.378 + return _vm_data[flag2index(flag)].committed_amount(); 1.379 + } 1.380 + // total memory (malloc'd + mmap'd + arena) of specified 1.381 + // memory type 1.382 + inline size_t total_amount(MEMFLAGS flag) const { 1.383 + int index = flag2index(flag); 1.384 + return _malloc_data[index].amount() + 1.385 + _vm_data[index].reserved_amount() + 1.386 + _arena_data[index].amount(); 1.387 + } 1.388 + 1.389 + /* overall summaries */ 1.390 + 1.391 + // total malloc'd memory in snapshot 1.392 + inline size_t total_malloc_amount() const { 1.393 + return _total_malloced; 1.394 + } 1.395 + // total mmap'd memory in snapshot 1.396 + inline size_t total_reserved_amount() const { 1.397 + return _total_vm_reserved; 1.398 + } 1.399 + // total committed memory in snapshot 1.400 + inline size_t total_committed_amount() const { 1.401 + return _total_vm_committed; 1.402 + } 1.403 + // number of loaded classes 1.404 + inline size_t number_of_classes() const { 1.405 + return _number_of_classes; 1.406 + } 1.407 + // number of running threads 1.408 + inline size_t number_of_threads() const { 1.409 + return _number_of_threads; 1.410 + } 1.411 + // lookup human readable name of a memory type 1.412 + static const char* type2name(MEMFLAGS type); 1.413 + 1.414 + private: 1.415 + // convert memory flag to the index to mapping table 1.416 + int flag2index(MEMFLAGS flag) const; 1.417 + 1.418 + // reset baseline values 1.419 + void reset(); 1.420 + 1.421 + // summarize the records in global snapshot 1.422 + bool baseline_malloc_summary(const MemPointerArray* malloc_records); 1.423 + bool baseline_vm_summary(const MemPointerArray* vm_records); 1.424 + bool baseline_malloc_details(const MemPointerArray* malloc_records); 1.425 + bool baseline_vm_details(const MemPointerArray* vm_records); 1.426 + 1.427 + // print a line of malloc'd memory aggregated by callsite 1.428 + void print_malloc_callsite(outputStream* st, address pc, size_t size, 1.429 + size_t count, int diff_amt, int diff_count) const; 1.430 + // print a line of mmap'd memory aggregated by callsite 1.431 + void print_vm_callsite(outputStream* st, address pc, size_t rsz, 1.432 + size_t csz, int diff_rsz, int diff_csz) const; 1.433 + 1.434 + // sorting functions for raw records 1.435 + static int malloc_sort_by_pc(const void* p1, const void* p2); 1.436 + static int malloc_sort_by_addr(const void* p1, const void* p2); 1.437 + 1.438 + static int vm_sort_by_pc(const void* p1, const void* p2); 1.439 + static int vm_sort_by_addr(const void* p1, const void* p2); 1.440 + 1.441 + private: 1.442 + // sorting functions for baselined records 1.443 + static int bl_malloc_sort_by_size(const void* p1, const void* p2); 1.444 + static int bl_vm_sort_by_size(const void* p1, const void* p2); 1.445 + static int bl_malloc_sort_by_pc(const void* p1, const void* p2); 1.446 + static int bl_vm_sort_by_pc(const void* p1, const void* p2); 1.447 +}; 1.448 + 1.449 + 1.450 +#endif // SHARE_VM_SERVICES_MEM_BASELINE_HPP