Mercurial > hg > graal-jvmci-8
comparison src/share/vm/services/memBaseline.hpp @ 20360:833b0f92429a
8046598: Scalable Native memory tracking development
Summary: Enhance scalability of native memory tracking
Reviewed-by: coleenp, ctornqvi, gtriantafill
author | zgu |
---|---|
date | Wed, 27 Aug 2014 08:19:12 -0400 |
parents | fbca7eaeac2e |
children | dd3939fe8424 |
comparison
equal
deleted
inserted
replaced
20359:4d3a43351904 | 20360:833b0f92429a |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. | 2 * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 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 | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
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 |