23 */ |
23 */ |
24 |
24 |
25 #ifndef SHARE_VM_SERVICES_MEM_BASELINE_HPP |
25 #ifndef SHARE_VM_SERVICES_MEM_BASELINE_HPP |
26 #define SHARE_VM_SERVICES_MEM_BASELINE_HPP |
26 #define SHARE_VM_SERVICES_MEM_BASELINE_HPP |
27 |
27 |
|
28 #if INCLUDE_NMT |
|
29 |
28 #include "memory/allocation.hpp" |
30 #include "memory/allocation.hpp" |
29 #include "runtime/mutex.hpp" |
31 #include "runtime/mutex.hpp" |
30 #include "services/memPtr.hpp" |
32 #include "services/mallocSiteTable.hpp" |
31 #include "services/memSnapshot.hpp" |
33 #include "services/mallocTracker.hpp" |
32 |
34 #include "services/nmtCommon.hpp" |
33 // compare unsigned number |
35 #include "services/virtualMemoryTracker.hpp" |
34 #define UNSIGNED_COMPARE(a, b) ((a > b) ? 1 : ((a == b) ? 0 : -1)) |
36 #include "utilities/linkedlist.hpp" |
|
37 |
|
38 typedef LinkedListIterator<MallocSite> MallocSiteIterator; |
|
39 typedef LinkedListIterator<VirtualMemoryAllocationSite> VirtualMemorySiteIterator; |
|
40 typedef LinkedListIterator<ReservedMemoryRegion> VirtualMemoryAllocationIterator; |
35 |
41 |
36 /* |
42 /* |
37 * MallocCallsitePointer and VMCallsitePointer are used |
43 * Baseline a memory snapshot |
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 VALUE_OBJ_CLASS_SPEC { |
|
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 VALUE_OBJ_CLASS_SPEC { |
|
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 */ |
44 */ |
299 class MemBaseline VALUE_OBJ_CLASS_SPEC { |
45 class MemBaseline VALUE_OBJ_CLASS_SPEC { |
300 friend class BaselineReporter; |
46 public: |
301 friend class BaselineComparisonReporter; |
47 enum BaselineThreshold { |
|
48 SIZE_THRESHOLD = K // Only allocation size over this threshold will be baselined. |
|
49 }; |
|
50 |
|
51 enum BaselineType { |
|
52 Not_baselined, |
|
53 Summary_baselined, |
|
54 Detail_baselined |
|
55 }; |
|
56 |
|
57 enum SortingOrder { |
|
58 by_address, // by memory address |
|
59 by_size, // by memory size |
|
60 by_site // by call site where the memory is allocated from |
|
61 }; |
302 |
62 |
303 private: |
63 private: |
304 // overall summaries |
64 // All baseline data is stored in this arena |
305 size_t _total_malloced; |
65 Arena* _arena; |
306 size_t _total_vm_reserved; |
66 |
307 size_t _total_vm_committed; |
67 // Summary information |
308 size_t _number_of_classes; |
68 MallocMemorySnapshot* _malloc_memory_snapshot; |
309 size_t _number_of_threads; |
69 VirtualMemorySnapshot* _virtual_memory_snapshot; |
310 |
70 |
311 // if it has properly baselined |
71 size_t _class_count; |
312 bool _baselined; |
72 |
313 |
73 // Allocation sites information |
314 // we categorize memory into three categories within the memory type |
74 // Malloc allocation sites |
315 MallocMem _malloc_data[NUMBER_OF_MEMORY_TYPE]; |
75 LinkedListImpl<MallocSite, ResourceObj::ARENA> |
316 VMMem _vm_data[NUMBER_OF_MEMORY_TYPE]; |
76 _malloc_sites; |
317 ArenaMem _arena_data[NUMBER_OF_MEMORY_TYPE]; |
77 |
318 |
78 // All virtual memory allocations |
319 // memory records that aggregate memory usage by callsites. |
79 LinkedListImpl<ReservedMemoryRegion, ResourceObj::ARENA> |
320 // only available when detail tracking is on. |
80 _virtual_memory_allocations; |
321 MemPointerArray* _malloc_cs; |
81 |
322 MemPointerArray* _vm_cs; |
82 // Virtual memory allocations by allocation sites, always in by_address |
323 // virtual memory map |
83 // order |
324 MemPointerArray* _vm_map; |
84 LinkedListImpl<VirtualMemoryAllocationSite, ResourceObj::ARENA> |
325 |
85 _virtual_memory_sites; |
326 private: |
86 |
327 static MemType2Name MemType2NameMap[NUMBER_OF_MEMORY_TYPE]; |
87 SortingOrder _malloc_sites_order; |
328 |
88 SortingOrder _virtual_memory_sites_order; |
329 private: |
89 |
330 // should not use copy constructor |
90 BaselineType _baseline_type; |
331 MemBaseline(MemBaseline& copy) { ShouldNotReachHere(); } |
|
332 |
|
333 // check and block at a safepoint |
|
334 static inline void check_safepoint(JavaThread* thr); |
|
335 |
91 |
336 public: |
92 public: |
337 // create a memory baseline |
93 // create a memory baseline |
338 MemBaseline(); |
94 MemBaseline(): |
339 |
95 _baseline_type(Not_baselined), |
340 ~MemBaseline(); |
96 _class_count(0), |
341 |
97 _arena(NULL), |
342 inline bool baselined() const { |
98 _malloc_memory_snapshot(NULL), |
343 return _baselined; |
99 _virtual_memory_snapshot(NULL), |
344 } |
100 _malloc_sites(NULL) { |
345 |
101 } |
346 MemBaseline& operator=(const MemBaseline& other); |
102 |
|
103 ~MemBaseline() { |
|
104 reset(); |
|
105 if (_arena != NULL) { |
|
106 delete _arena; |
|
107 } |
|
108 } |
|
109 |
|
110 bool baseline(bool summaryOnly = true); |
|
111 |
|
112 BaselineType baseline_type() const { return _baseline_type; } |
|
113 |
|
114 MallocMemorySnapshot* malloc_memory_snapshot() const { |
|
115 return _malloc_memory_snapshot; |
|
116 } |
|
117 |
|
118 VirtualMemorySnapshot* virtual_memory_snapshot() const { |
|
119 return _virtual_memory_snapshot; |
|
120 } |
|
121 |
|
122 MallocSiteIterator malloc_sites(SortingOrder order); |
|
123 VirtualMemorySiteIterator virtual_memory_sites(SortingOrder order); |
|
124 |
|
125 // Virtual memory allocation iterator always returns in virtual memory |
|
126 // base address order. |
|
127 VirtualMemoryAllocationIterator virtual_memory_allocations() { |
|
128 assert(!_virtual_memory_allocations.is_empty(), "Not detail baseline"); |
|
129 return VirtualMemoryAllocationIterator(_virtual_memory_allocations.head()); |
|
130 } |
|
131 |
|
132 // Total reserved memory = total malloc'd memory + total reserved virtual |
|
133 // memory |
|
134 size_t total_reserved_memory() const { |
|
135 assert(baseline_type() != Not_baselined, "Not yet baselined"); |
|
136 assert(_virtual_memory_snapshot != NULL, "No virtual memory snapshot"); |
|
137 assert(_malloc_memory_snapshot != NULL, "No malloc memory snapshot"); |
|
138 size_t amount = _malloc_memory_snapshot->total() + |
|
139 _virtual_memory_snapshot->total_reserved(); |
|
140 return amount; |
|
141 } |
|
142 |
|
143 // Total committed memory = total malloc'd memory + total committed |
|
144 // virtual memory |
|
145 size_t total_committed_memory() const { |
|
146 assert(baseline_type() != Not_baselined, "Not yet baselined"); |
|
147 assert(_virtual_memory_snapshot != NULL, |
|
148 "Not a snapshot"); |
|
149 size_t amount = _malloc_memory_snapshot->total() + |
|
150 _virtual_memory_snapshot->total_committed(); |
|
151 return amount; |
|
152 } |
|
153 |
|
154 size_t total_arena_memory() const { |
|
155 assert(baseline_type() != Not_baselined, "Not yet baselined"); |
|
156 assert(_malloc_memory_snapshot != NULL, "Not yet baselined"); |
|
157 return _malloc_memory_snapshot->total_arena(); |
|
158 } |
|
159 |
|
160 size_t malloc_tracking_overhead() const { |
|
161 assert(baseline_type() != Not_baselined, "Not yet baselined"); |
|
162 return _malloc_memory_snapshot->malloc_overhead()->size(); |
|
163 } |
|
164 |
|
165 const MallocMemory* malloc_memory(MEMFLAGS flag) const { |
|
166 assert(_malloc_memory_snapshot != NULL, "Not a snapshot"); |
|
167 return _malloc_memory_snapshot->by_type(flag); |
|
168 } |
|
169 |
|
170 const VirtualMemory* virtual_memory(MEMFLAGS flag) const { |
|
171 assert(_virtual_memory_snapshot != NULL, "Not a snapshot"); |
|
172 return _virtual_memory_snapshot->by_type(flag); |
|
173 } |
|
174 |
|
175 |
|
176 size_t class_count() const { |
|
177 assert(baseline_type() != Not_baselined, "Not yet baselined"); |
|
178 return _class_count; |
|
179 } |
|
180 |
|
181 size_t thread_count() const { |
|
182 assert(baseline_type() != Not_baselined, "Not yet baselined"); |
|
183 assert(_malloc_memory_snapshot != NULL, "Baselined?"); |
|
184 return _malloc_memory_snapshot->thread_count(); |
|
185 } |
347 |
186 |
348 // reset the baseline for reuse |
187 // reset the baseline for reuse |
349 void clear(); |
188 void reset() { |
350 |
189 _baseline_type = Not_baselined; |
351 // baseline the snapshot |
190 _malloc_memory_snapshot = NULL; |
352 bool baseline(MemSnapshot& snapshot, bool summary_only = true); |
191 _virtual_memory_snapshot = NULL; |
353 |
192 _class_count = 0; |
354 bool baseline(const MemPointerArray* malloc_records, |
193 |
355 const MemPointerArray* vm_records, |
194 _malloc_sites = NULL; |
356 bool summary_only = true); |
195 _virtual_memory_sites = NULL; |
357 |
196 _virtual_memory_allocations = NULL; |
358 // total malloc'd memory of specified memory type |
197 |
359 inline size_t malloc_amount(MEMFLAGS flag) const { |
198 if (_arena != NULL) { |
360 return _malloc_data[flag2index(flag)].amount(); |
199 _arena->destruct_contents(); |
361 } |
200 } |
362 // number of malloc'd memory blocks of specified memory type |
201 } |
363 inline size_t malloc_count(MEMFLAGS flag) const { |
|
364 return _malloc_data[flag2index(flag)].count(); |
|
365 } |
|
366 // total memory used by arenas of specified memory type |
|
367 inline size_t arena_amount(MEMFLAGS flag) const { |
|
368 return _arena_data[flag2index(flag)].amount(); |
|
369 } |
|
370 // number of arenas of specified memory type |
|
371 inline size_t arena_count(MEMFLAGS flag) const { |
|
372 return _arena_data[flag2index(flag)].count(); |
|
373 } |
|
374 // total reserved memory of specified memory type |
|
375 inline size_t reserved_amount(MEMFLAGS flag) const { |
|
376 return _vm_data[flag2index(flag)].reserved_amount(); |
|
377 } |
|
378 // total committed memory of specified memory type |
|
379 inline size_t committed_amount(MEMFLAGS flag) const { |
|
380 return _vm_data[flag2index(flag)].committed_amount(); |
|
381 } |
|
382 // total memory (malloc'd + mmap'd + arena) of specified |
|
383 // memory type |
|
384 inline size_t total_amount(MEMFLAGS flag) const { |
|
385 int index = flag2index(flag); |
|
386 return _malloc_data[index].amount() + |
|
387 _vm_data[index].reserved_amount() + |
|
388 _arena_data[index].amount(); |
|
389 } |
|
390 |
|
391 /* overall summaries */ |
|
392 |
|
393 // total malloc'd memory in snapshot |
|
394 inline size_t total_malloc_amount() const { |
|
395 return _total_malloced; |
|
396 } |
|
397 // total mmap'd memory in snapshot |
|
398 inline size_t total_reserved_amount() const { |
|
399 return _total_vm_reserved; |
|
400 } |
|
401 // total committed memory in snapshot |
|
402 inline size_t total_committed_amount() const { |
|
403 return _total_vm_committed; |
|
404 } |
|
405 // number of loaded classes |
|
406 inline size_t number_of_classes() const { |
|
407 return _number_of_classes; |
|
408 } |
|
409 // number of running threads |
|
410 inline size_t number_of_threads() const { |
|
411 return _number_of_threads; |
|
412 } |
|
413 // lookup human readable name of a memory type |
|
414 static const char* type2name(MEMFLAGS type); |
|
415 |
202 |
416 private: |
203 private: |
417 // convert memory flag to the index to mapping table |
204 // Baseline summary information |
418 int flag2index(MEMFLAGS flag) const; |
205 bool baseline_summary(); |
419 |
206 |
420 // reset baseline values |
207 // Baseline allocation sites (detail tracking only) |
421 void reset(); |
208 bool baseline_allocation_sites(); |
422 |
209 |
423 // summarize the records in global snapshot |
210 // Aggregate virtual memory allocation by allocation sites |
424 bool baseline_malloc_summary(const MemPointerArray* malloc_records); |
211 bool aggregate_virtual_memory_allocation_sites(); |
425 bool baseline_vm_summary(const MemPointerArray* vm_records); |
212 |
426 bool baseline_malloc_details(const MemPointerArray* malloc_records); |
213 Arena* arena() { return _arena; } |
427 bool baseline_vm_details(const MemPointerArray* vm_records); |
214 |
428 |
215 // Sorting allocation sites in different orders |
429 // print a line of malloc'd memory aggregated by callsite |
216 // Sort allocation sites in size order |
430 void print_malloc_callsite(outputStream* st, address pc, size_t size, |
217 void malloc_sites_to_size_order(); |
431 size_t count, int diff_amt, int diff_count) const; |
218 // Sort allocation sites in call site address order |
432 // print a line of mmap'd memory aggregated by callsite |
219 void malloc_sites_to_allocation_site_order(); |
433 void print_vm_callsite(outputStream* st, address pc, size_t rsz, |
220 |
434 size_t csz, int diff_rsz, int diff_csz) const; |
221 // Sort allocation sites in reserved size order |
435 |
222 void virtual_memory_sites_to_size_order(); |
436 // sorting functions for raw records |
223 // Sort allocation sites in call site address order |
437 static int malloc_sort_by_pc(const void* p1, const void* p2); |
224 void virtual_memory_sites_to_reservation_site_order(); |
438 static int malloc_sort_by_addr(const void* p1, const void* p2); |
|
439 |
|
440 private: |
|
441 // sorting functions for baselined records |
|
442 static int bl_malloc_sort_by_size(const void* p1, const void* p2); |
|
443 static int bl_vm_sort_by_size(const void* p1, const void* p2); |
|
444 static int bl_malloc_sort_by_pc(const void* p1, const void* p2); |
|
445 static int bl_vm_sort_by_pc(const void* p1, const void* p2); |
|
446 }; |
225 }; |
447 |
226 |
|
227 #endif // INCLUDE_NMT |
448 |
228 |
449 #endif // SHARE_VM_SERVICES_MEM_BASELINE_HPP |
229 #endif // SHARE_VM_SERVICES_MEM_BASELINE_HPP |