Mercurial > hg > graal-compiler
annotate src/share/vm/services/memBaseline.cpp @ 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 | 72fce0b2d341 |
children | dd3939fe8424 |
rev | line source |
---|---|
6197 | 1 /* |
20360 | 2 * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. |
6197 | 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 #include "precompiled.hpp" | |
20360 | 25 |
6197 | 26 #include "memory/allocation.hpp" |
10148 | 27 #include "runtime/safepoint.hpp" |
28 #include "runtime/thread.inline.hpp" | |
6197 | 29 #include "services/memBaseline.hpp" |
30 #include "services/memTracker.hpp" | |
31 | |
20360 | 32 /* |
33 * Sizes are sorted in descenting order for reporting | |
34 */ | |
35 int compare_malloc_size(const MallocSite& s1, const MallocSite& s2) { | |
36 if (s1.size() == s2.size()) { | |
37 return 0; | |
38 } else if (s1.size() > s2.size()) { | |
39 return -1; | |
40 } else { | |
41 return 1; | |
6197 | 42 } |
43 } | |
44 | |
45 | |
20360 | 46 int compare_virtual_memory_size(const VirtualMemoryAllocationSite& s1, |
47 const VirtualMemoryAllocationSite& s2) { | |
48 if (s1.reserved() == s2.reserved()) { | |
49 return 0; | |
50 } else if (s1.reserved() > s2.reserved()) { | |
51 return -1; | |
52 } else { | |
53 return 1; | |
6197 | 54 } |
20360 | 55 } |
6197 | 56 |
20360 | 57 // Sort into allocation site addresses order for baseline comparison |
58 int compare_malloc_site(const MallocSite& s1, const MallocSite& s2) { | |
59 return s1.call_stack()->compare(*s2.call_stack()); | |
6197 | 60 } |
61 | |
62 | |
20360 | 63 int compare_virtual_memory_site(const VirtualMemoryAllocationSite& s1, |
64 const VirtualMemoryAllocationSite& s2) { | |
65 return s1.call_stack()->compare(*s2.call_stack()); | |
6197 | 66 } |
67 | |
20360 | 68 /* |
69 * Walker to walk malloc allocation site table | |
70 */ | |
71 class MallocAllocationSiteWalker : public MallocSiteWalker { | |
72 private: | |
73 SortedLinkedList<MallocSite, compare_malloc_size, ResourceObj::ARENA> | |
74 _malloc_sites; | |
75 size_t _count; | |
76 | |
77 // Entries in MallocSiteTable with size = 0 and count = 0, | |
78 // when the malloc site is not longer there. | |
79 public: | |
80 MallocAllocationSiteWalker(Arena* arena) : _count(0), _malloc_sites(arena) { | |
81 } | |
82 | |
83 inline size_t count() const { return _count; } | |
84 | |
85 LinkedList<MallocSite>* malloc_sites() { | |
86 return &_malloc_sites; | |
87 } | |
88 | |
89 bool do_malloc_site(const MallocSite* site) { | |
90 if (site->size() >= MemBaseline::SIZE_THRESHOLD) { | |
91 if (_malloc_sites.add(*site) != NULL) { | |
92 _count++; | |
93 return true; | |
94 } else { | |
95 return false; // OOM | |
96 } | |
97 } else { | |
98 // malloc site does not meet threshold, ignore and continue | |
99 return true; | |
100 } | |
101 } | |
102 }; | |
103 | |
104 // Compare virtual memory region's base address | |
105 int compare_virtual_memory_base(const ReservedMemoryRegion& r1, const ReservedMemoryRegion& r2) { | |
106 return r1.compare(r2); | |
6197 | 107 } |
108 | |
20360 | 109 // Walk all virtual memory regions for baselining |
110 class VirtualMemoryAllocationWalker : public VirtualMemoryWalker { | |
111 private: | |
112 SortedLinkedList<ReservedMemoryRegion, compare_virtual_memory_base, ResourceObj::ARENA> | |
113 _virtual_memory_regions; | |
114 size_t _count; | |
115 | |
116 public: | |
117 VirtualMemoryAllocationWalker(Arena* a) : _count(0), _virtual_memory_regions(a) { | |
118 } | |
119 | |
120 bool do_allocation_site(const ReservedMemoryRegion* rgn) { | |
121 if (rgn->size() >= MemBaseline::SIZE_THRESHOLD) { | |
122 if (_virtual_memory_regions.add(*rgn) != NULL) { | |
123 _count ++; | |
124 return true; | |
125 } else { | |
126 return false; | |
6197 | 127 } |
128 } | |
20360 | 129 return true; |
6197 | 130 } |
131 | |
20360 | 132 LinkedList<ReservedMemoryRegion>* virtual_memory_allocations() { |
133 return &_virtual_memory_regions; | |
134 } | |
135 }; | |
136 | |
137 | |
138 bool MemBaseline::baseline_summary() { | |
139 assert(_malloc_memory_snapshot == NULL, "Malloc baseline not yet reset"); | |
140 assert(_virtual_memory_snapshot == NULL, "Virtual baseline not yet reset"); | |
141 | |
142 _malloc_memory_snapshot = new (arena()) MallocMemorySnapshot(); | |
143 _virtual_memory_snapshot = new (arena()) VirtualMemorySnapshot(); | |
144 if (_malloc_memory_snapshot == NULL || _virtual_memory_snapshot == NULL) { | |
145 return false; | |
146 } | |
147 MallocMemorySummary::snapshot(_malloc_memory_snapshot); | |
148 VirtualMemorySummary::snapshot(_virtual_memory_snapshot); | |
149 return true; | |
150 } | |
151 | |
152 bool MemBaseline::baseline_allocation_sites() { | |
153 assert(arena() != NULL, "Just check"); | |
154 // Malloc allocation sites | |
155 MallocAllocationSiteWalker malloc_walker(arena()); | |
156 if (!MallocSiteTable::walk_malloc_site(&malloc_walker)) { | |
157 return false; | |
158 } | |
159 | |
160 _malloc_sites.set_head(malloc_walker.malloc_sites()->head()); | |
161 // The malloc sites are collected in size order | |
162 _malloc_sites_order = by_size; | |
163 | |
164 // Virtual memory allocation sites | |
165 VirtualMemoryAllocationWalker virtual_memory_walker(arena()); | |
166 if (!VirtualMemoryTracker::walk_virtual_memory(&virtual_memory_walker)) { | |
167 return false; | |
168 } | |
169 | |
170 // Virtual memory allocations are collected in call stack order | |
171 _virtual_memory_allocations.set_head(virtual_memory_walker.virtual_memory_allocations()->head()); | |
172 | |
173 if (!aggregate_virtual_memory_allocation_sites()) { | |
174 return false; | |
175 } | |
176 // Virtual memory allocation sites are aggregrated in call stack order | |
177 _virtual_memory_sites_order = by_address; | |
6197 | 178 |
179 return true; | |
180 } | |
181 | |
20360 | 182 bool MemBaseline::baseline(bool summaryOnly) { |
183 if (arena() == NULL) { | |
184 _arena = new (std::nothrow, mtNMT) Arena(mtNMT); | |
185 if (arena() == NULL) return false; | |
6197 | 186 } |
187 | |
20360 | 188 reset(); |
6882
716c64bda5ba
7199092: NMT: NMT needs to deal overlapped virtual memory ranges
zgu
parents:
6197
diff
changeset
|
189 |
20360 | 190 _class_count = InstanceKlass::number_of_instance_classes(); |
6882
716c64bda5ba
7199092: NMT: NMT needs to deal overlapped virtual memory ranges
zgu
parents:
6197
diff
changeset
|
191 |
20360 | 192 if (!baseline_summary()) { |
6882
716c64bda5ba
7199092: NMT: NMT needs to deal overlapped virtual memory ranges
zgu
parents:
6197
diff
changeset
|
193 return false; |
716c64bda5ba
7199092: NMT: NMT needs to deal overlapped virtual memory ranges
zgu
parents:
6197
diff
changeset
|
194 } |
716c64bda5ba
7199092: NMT: NMT needs to deal overlapped virtual memory ranges
zgu
parents:
6197
diff
changeset
|
195 |
20360 | 196 _baseline_type = Summary_baselined; |
6882
716c64bda5ba
7199092: NMT: NMT needs to deal overlapped virtual memory ranges
zgu
parents:
6197
diff
changeset
|
197 |
20360 | 198 // baseline details |
199 if (!summaryOnly && | |
200 MemTracker::tracking_level() == NMT_detail) { | |
201 baseline_allocation_sites(); | |
202 _baseline_type = Detail_baselined; | |
6882
716c64bda5ba
7199092: NMT: NMT needs to deal overlapped virtual memory ranges
zgu
parents:
6197
diff
changeset
|
203 } |
716c64bda5ba
7199092: NMT: NMT needs to deal overlapped virtual memory ranges
zgu
parents:
6197
diff
changeset
|
204 |
6197 | 205 return true; |
206 } | |
207 | |
20360 | 208 int compare_allocation_site(const VirtualMemoryAllocationSite& s1, |
209 const VirtualMemoryAllocationSite& s2) { | |
210 return s1.call_stack()->compare(*s2.call_stack()); | |
211 } | |
212 | |
213 bool MemBaseline::aggregate_virtual_memory_allocation_sites() { | |
214 SortedLinkedList<VirtualMemoryAllocationSite, compare_allocation_site, ResourceObj::ARENA> | |
215 allocation_sites(arena()); | |
216 | |
217 VirtualMemoryAllocationIterator itr = virtual_memory_allocations(); | |
218 const ReservedMemoryRegion* rgn; | |
219 VirtualMemoryAllocationSite* site; | |
220 while ((rgn = itr.next()) != NULL) { | |
221 VirtualMemoryAllocationSite tmp(*rgn->call_stack()); | |
222 site = allocation_sites.find(tmp); | |
223 if (site == NULL) { | |
224 LinkedListNode<VirtualMemoryAllocationSite>* node = | |
225 allocation_sites.add(tmp); | |
226 if (node == NULL) return false; | |
227 site = node->data(); | |
228 } | |
229 site->reserve_memory(rgn->size()); | |
230 site->commit_memory(rgn->committed_size()); | |
10148 | 231 } |
6197 | 232 |
20360 | 233 _virtual_memory_sites.set_head(allocation_sites.head()); |
234 return true; | |
6197 | 235 } |
236 | |
20360 | 237 MallocSiteIterator MemBaseline::malloc_sites(SortingOrder order) { |
238 assert(!_malloc_sites.is_empty(), "Detail baseline?"); | |
239 switch(order) { | |
240 case by_size: | |
241 malloc_sites_to_size_order(); | |
242 break; | |
243 case by_site: | |
244 malloc_sites_to_allocation_site_order(); | |
245 break; | |
246 case by_address: | |
247 default: | |
248 ShouldNotReachHere(); | |
6197 | 249 } |
20360 | 250 return MallocSiteIterator(_malloc_sites.head()); |
6197 | 251 } |
252 | |
20360 | 253 VirtualMemorySiteIterator MemBaseline::virtual_memory_sites(SortingOrder order) { |
254 assert(!_virtual_memory_sites.is_empty(), "Detail baseline?"); | |
255 switch(order) { | |
256 case by_size: | |
257 virtual_memory_sites_to_size_order(); | |
258 break; | |
259 case by_site: | |
260 virtual_memory_sites_to_reservation_site_order(); | |
261 break; | |
262 case by_address: | |
263 default: | |
264 ShouldNotReachHere(); | |
6197 | 265 } |
20360 | 266 return VirtualMemorySiteIterator(_virtual_memory_sites.head()); |
6197 | 267 } |
268 | |
269 | |
20360 | 270 // Sorting allocations sites in different orders |
271 void MemBaseline::malloc_sites_to_size_order() { | |
272 if (_malloc_sites_order != by_size) { | |
273 SortedLinkedList<MallocSite, compare_malloc_size, ResourceObj::ARENA> | |
274 tmp(arena()); | |
6197 | 275 |
20360 | 276 // Add malloc sites to sorted linked list to sort into size order |
277 tmp.move(&_malloc_sites); | |
278 _malloc_sites.set_head(tmp.head()); | |
279 tmp.set_head(NULL); | |
280 _malloc_sites_order = by_size; | |
6197 | 281 } |
282 } | |
283 | |
20360 | 284 void MemBaseline::malloc_sites_to_allocation_site_order() { |
285 if (_malloc_sites_order != by_site) { | |
286 SortedLinkedList<MallocSite, compare_malloc_site, ResourceObj::ARENA> | |
287 tmp(arena()); | |
288 // Add malloc sites to sorted linked list to sort into site (address) order | |
289 tmp.move(&_malloc_sites); | |
290 _malloc_sites.set_head(tmp.head()); | |
291 tmp.set_head(NULL); | |
292 _malloc_sites_order = by_site; | |
293 } | |
6197 | 294 } |
295 | |
20360 | 296 void MemBaseline::virtual_memory_sites_to_size_order() { |
297 if (_virtual_memory_sites_order != by_size) { | |
298 SortedLinkedList<VirtualMemoryAllocationSite, compare_virtual_memory_size, ResourceObj::ARENA> | |
299 tmp(arena()); | |
6197 | 300 |
20360 | 301 tmp.move(&_virtual_memory_sites); |
302 | |
303 _virtual_memory_sites.set_head(tmp.head()); | |
304 tmp.set_head(NULL); | |
305 _virtual_memory_sites_order = by_size; | |
306 } | |
6197 | 307 } |
308 | |
20360 | 309 void MemBaseline::virtual_memory_sites_to_reservation_site_order() { |
310 if (_virtual_memory_sites_order != by_size) { | |
311 SortedLinkedList<VirtualMemoryAllocationSite, compare_virtual_memory_site, ResourceObj::ARENA> | |
312 tmp(arena()); | |
6197 | 313 |
20360 | 314 tmp.add(&_virtual_memory_sites); |
315 | |
316 _virtual_memory_sites.set_head(tmp.head()); | |
317 tmp.set_head(NULL); | |
318 | |
319 _virtual_memory_sites_order = by_size; | |
320 } | |
6197 | 321 } |
322 |