83 _total_malloced = 0; |
90 _total_malloced = 0; |
84 _number_of_classes = 0; |
91 _number_of_classes = 0; |
85 |
92 |
86 if (_malloc_cs != NULL) _malloc_cs->clear(); |
93 if (_malloc_cs != NULL) _malloc_cs->clear(); |
87 if (_vm_cs != NULL) _vm_cs->clear(); |
94 if (_vm_cs != NULL) _vm_cs->clear(); |
|
95 if (_vm_map != NULL) _vm_map->clear(); |
88 |
96 |
89 for (int index = 0; index < NUMBER_OF_MEMORY_TYPE; index ++) { |
97 for (int index = 0; index < NUMBER_OF_MEMORY_TYPE; index ++) { |
90 _malloc_data[index].clear(); |
98 _malloc_data[index].clear(); |
91 _vm_data[index].clear(); |
99 _vm_data[index].clear(); |
92 _arena_data[index].clear(); |
100 _arena_data[index].clear(); |
93 } |
101 } |
94 } |
102 } |
95 |
103 |
96 MemBaseline::~MemBaseline() { |
104 MemBaseline::~MemBaseline() { |
97 if (_malloc_cs != NULL) { |
105 clear(); |
98 delete _malloc_cs; |
|
99 } |
|
100 |
|
101 if (_vm_cs != NULL) { |
|
102 delete _vm_cs; |
|
103 } |
|
104 } |
106 } |
105 |
107 |
106 // baseline malloc'd memory records, generate overall summary and summaries by |
108 // baseline malloc'd memory records, generate overall summary and summaries by |
107 // memory types |
109 // memory types |
108 bool MemBaseline::baseline_malloc_summary(const MemPointerArray* malloc_records) { |
110 bool MemBaseline::baseline_malloc_summary(const MemPointerArray* malloc_records) { |
109 MemPointerArrayIteratorImpl mItr((MemPointerArray*)malloc_records); |
111 MemPointerArrayIteratorImpl malloc_itr((MemPointerArray*)malloc_records); |
110 MemPointerRecord* mptr = (MemPointerRecord*)mItr.current(); |
112 MemPointerRecord* malloc_ptr = (MemPointerRecord*)malloc_itr.current(); |
111 size_t used_arena_size = 0; |
113 size_t used_arena_size = 0; |
112 int index; |
114 int index; |
113 while (mptr != NULL) { |
115 while (malloc_ptr != NULL) { |
114 index = flag2index(FLAGS_TO_MEMORY_TYPE(mptr->flags())); |
116 index = flag2index(FLAGS_TO_MEMORY_TYPE(malloc_ptr->flags())); |
115 size_t size = mptr->size(); |
117 size_t size = malloc_ptr->size(); |
116 _total_malloced += size; |
118 _total_malloced += size; |
117 _malloc_data[index].inc(size); |
119 _malloc_data[index].inc(size); |
118 if (MemPointerRecord::is_arena_record(mptr->flags())) { |
120 if (MemPointerRecord::is_arena_record(malloc_ptr->flags())) { |
119 // see if arena size record present |
121 // see if arena size record present |
120 MemPointerRecord* next_p = (MemPointerRecordEx*)mItr.peek_next(); |
122 MemPointerRecord* next_malloc_ptr = (MemPointerRecordEx*)malloc_itr.peek_next(); |
121 if (MemPointerRecord::is_arena_size_record(next_p->flags())) { |
123 if (MemPointerRecord::is_arena_size_record(next_malloc_ptr->flags())) { |
122 assert(next_p->is_size_record_of_arena(mptr), "arena records do not match"); |
124 assert(next_malloc_ptr->is_size_record_of_arena(malloc_ptr), "arena records do not match"); |
123 size = next_p->size(); |
125 size = next_malloc_ptr->size(); |
124 _arena_data[index].inc(size); |
126 _arena_data[index].inc(size); |
125 used_arena_size += size; |
127 used_arena_size += size; |
126 mItr.next(); |
128 malloc_itr.next(); |
127 } |
129 } |
128 } |
130 } |
129 mptr = (MemPointerRecordEx*)mItr.next(); |
131 malloc_ptr = (MemPointerRecordEx*)malloc_itr.next(); |
130 } |
132 } |
131 |
133 |
132 // substract used arena size to get size of arena chunk in free list |
134 // substract used arena size to get size of arena chunk in free list |
133 index = flag2index(mtChunk); |
135 index = flag2index(mtChunk); |
134 _malloc_data[index].reduce(used_arena_size); |
136 _malloc_data[index].reduce(used_arena_size); |
140 } |
142 } |
141 |
143 |
142 // baseline mmap'd memory records, generate overall summary and summaries by |
144 // baseline mmap'd memory records, generate overall summary and summaries by |
143 // memory types |
145 // memory types |
144 bool MemBaseline::baseline_vm_summary(const MemPointerArray* vm_records) { |
146 bool MemBaseline::baseline_vm_summary(const MemPointerArray* vm_records) { |
145 MemPointerArrayIteratorImpl vItr((MemPointerArray*)vm_records); |
147 MemPointerArrayIteratorImpl vm_itr((MemPointerArray*)vm_records); |
146 VMMemRegion* vptr = (VMMemRegion*)vItr.current(); |
148 VMMemRegion* vm_ptr = (VMMemRegion*)vm_itr.current(); |
147 int index; |
149 int index; |
148 while (vptr != NULL) { |
150 while (vm_ptr != NULL) { |
149 index = flag2index(FLAGS_TO_MEMORY_TYPE(vptr->flags())); |
151 if (vm_ptr->is_reserved_region()) { |
150 |
152 index = flag2index(FLAGS_TO_MEMORY_TYPE(vm_ptr->flags())); |
151 // we use the number of thread stack to count threads |
153 // we use the number of thread stack to count threads |
152 if (IS_MEMORY_TYPE(vptr->flags(), mtThreadStack)) { |
154 if (IS_MEMORY_TYPE(vm_ptr->flags(), mtThreadStack)) { |
153 _number_of_threads ++; |
155 _number_of_threads ++; |
154 } |
156 } |
155 _total_vm_reserved += vptr->reserved_size(); |
157 _total_vm_reserved += vm_ptr->size(); |
156 _total_vm_committed += vptr->committed_size(); |
158 _vm_data[index].inc(vm_ptr->size(), 0); |
157 _vm_data[index].inc(vptr->reserved_size(), vptr->committed_size()); |
159 } else { |
158 vptr = (VMMemRegion*)vItr.next(); |
160 _total_vm_committed += vm_ptr->size(); |
|
161 _vm_data[index].inc(0, vm_ptr->size()); |
|
162 } |
|
163 vm_ptr = (VMMemRegion*)vm_itr.next(); |
159 } |
164 } |
160 return true; |
165 return true; |
161 } |
166 } |
162 |
167 |
163 // baseline malloc'd memory by callsites, but only the callsites with memory allocation |
168 // baseline malloc'd memory by callsites, but only the callsites with memory allocation |
164 // over 1KB are stored. |
169 // over 1KB are stored. |
165 bool MemBaseline::baseline_malloc_details(const MemPointerArray* malloc_records) { |
170 bool MemBaseline::baseline_malloc_details(const MemPointerArray* malloc_records) { |
166 assert(MemTracker::track_callsite(), "detail tracking is off"); |
171 assert(MemTracker::track_callsite(), "detail tracking is off"); |
167 |
172 |
168 MemPointerArrayIteratorImpl mItr((MemPointerArray*)malloc_records); |
173 MemPointerArrayIteratorImpl malloc_itr(const_cast<MemPointerArray*>(malloc_records)); |
169 MemPointerRecordEx* mptr = (MemPointerRecordEx*)mItr.current(); |
174 MemPointerRecordEx* malloc_ptr = (MemPointerRecordEx*)malloc_itr.current(); |
170 MallocCallsitePointer mp; |
175 MallocCallsitePointer malloc_callsite; |
171 |
176 |
|
177 // initailize malloc callsite array |
172 if (_malloc_cs == NULL) { |
178 if (_malloc_cs == NULL) { |
173 _malloc_cs = new (std::nothrow) MemPointerArrayImpl<MallocCallsitePointer>(64); |
179 _malloc_cs = new (std::nothrow) MemPointerArrayImpl<MallocCallsitePointer>(64); |
174 // out of native memory |
180 // out of native memory |
175 if (_malloc_cs == NULL) { |
181 if (_malloc_cs == NULL || _malloc_cs->out_of_memory()) { |
176 return false; |
182 return false; |
177 } |
183 } |
178 } else { |
184 } else { |
179 _malloc_cs->clear(); |
185 _malloc_cs->clear(); |
180 } |
186 } |
181 |
187 |
|
188 MemPointerArray* malloc_data = const_cast<MemPointerArray*>(malloc_records); |
|
189 |
|
190 // sort into callsite pc order. Details are aggregated by callsites |
|
191 malloc_data->sort((FN_SORT)malloc_sort_by_pc); |
|
192 bool ret = true; |
|
193 |
182 // baseline memory that is totaled over 1 KB |
194 // baseline memory that is totaled over 1 KB |
183 while (mptr != NULL) { |
195 while (malloc_ptr != NULL) { |
184 if (!MemPointerRecord::is_arena_size_record(mptr->flags())) { |
196 if (!MemPointerRecord::is_arena_size_record(malloc_ptr->flags())) { |
185 // skip thread stacks |
197 // skip thread stacks |
186 if (!IS_MEMORY_TYPE(mptr->flags(), mtThreadStack)) { |
198 if (!IS_MEMORY_TYPE(malloc_ptr->flags(), mtThreadStack)) { |
187 if (mp.addr() != mptr->pc()) { |
199 if (malloc_callsite.addr() != malloc_ptr->pc()) { |
188 if ((mp.amount()/K) > 0) { |
200 if ((malloc_callsite.amount()/K) > 0) { |
189 if (!_malloc_cs->append(&mp)) { |
201 if (!_malloc_cs->append(&malloc_callsite)) { |
|
202 ret = false; |
|
203 break; |
|
204 } |
|
205 } |
|
206 malloc_callsite = MallocCallsitePointer(malloc_ptr->pc()); |
|
207 } |
|
208 malloc_callsite.inc(malloc_ptr->size()); |
|
209 } |
|
210 } |
|
211 malloc_ptr = (MemPointerRecordEx*)malloc_itr.next(); |
|
212 } |
|
213 |
|
214 // restore to address order. Snapshot malloc data is maintained in memory |
|
215 // address order. |
|
216 malloc_data->sort((FN_SORT)malloc_sort_by_addr); |
|
217 |
|
218 if (!ret) { |
190 return false; |
219 return false; |
191 } |
220 } |
192 } |
221 // deal with last record |
193 mp = MallocCallsitePointer(mptr->pc()); |
222 if (malloc_callsite.addr() != 0 && (malloc_callsite.amount()/K) > 0) { |
194 } |
223 if (!_malloc_cs->append(&malloc_callsite)) { |
195 mp.inc(mptr->size()); |
|
196 } |
|
197 } |
|
198 mptr = (MemPointerRecordEx*)mItr.next(); |
|
199 } |
|
200 |
|
201 if (mp.addr() != 0 && (mp.amount()/K) > 0) { |
|
202 if (!_malloc_cs->append(&mp)) { |
|
203 return false; |
224 return false; |
204 } |
225 } |
205 } |
226 } |
206 return true; |
227 return true; |
207 } |
228 } |
208 |
229 |
209 // baseline mmap'd memory by callsites |
230 // baseline mmap'd memory by callsites |
210 bool MemBaseline::baseline_vm_details(const MemPointerArray* vm_records) { |
231 bool MemBaseline::baseline_vm_details(const MemPointerArray* vm_records) { |
211 assert(MemTracker::track_callsite(), "detail tracking is off"); |
232 assert(MemTracker::track_callsite(), "detail tracking is off"); |
212 |
233 |
213 VMCallsitePointer vp; |
234 VMCallsitePointer vm_callsite; |
214 MemPointerArrayIteratorImpl vItr((MemPointerArray*)vm_records); |
235 VMCallsitePointer* cur_callsite = NULL; |
215 VMMemRegionEx* vptr = (VMMemRegionEx*)vItr.current(); |
236 MemPointerArrayIteratorImpl vm_itr((MemPointerArray*)vm_records); |
216 |
237 VMMemRegionEx* vm_ptr = (VMMemRegionEx*)vm_itr.current(); |
|
238 |
|
239 // initialize virtual memory map array |
|
240 if (_vm_map == NULL) { |
|
241 _vm_map = new (std::nothrow) MemPointerArrayImpl<VMMemRegionEx>(vm_records->length()); |
|
242 if (_vm_map == NULL || _vm_map->out_of_memory()) { |
|
243 return false; |
|
244 } |
|
245 } else { |
|
246 _vm_map->clear(); |
|
247 } |
|
248 |
|
249 // initialize virtual memory callsite array |
217 if (_vm_cs == NULL) { |
250 if (_vm_cs == NULL) { |
218 _vm_cs = new (std::nothrow) MemPointerArrayImpl<VMCallsitePointer>(64); |
251 _vm_cs = new (std::nothrow) MemPointerArrayImpl<VMCallsitePointer>(64); |
219 if (_vm_cs == NULL) { |
252 if (_vm_cs == NULL || _vm_cs->out_of_memory()) { |
220 return false; |
253 return false; |
221 } |
254 } |
222 } else { |
255 } else { |
223 _vm_cs->clear(); |
256 _vm_cs->clear(); |
224 } |
257 } |
225 |
258 |
226 while (vptr != NULL) { |
259 // consolidate virtual memory data |
227 if (vp.addr() != vptr->pc()) { |
260 VMMemRegionEx* reserved_rec = NULL; |
228 if (!_vm_cs->append(&vp)) { |
261 VMMemRegionEx* committed_rec = NULL; |
|
262 |
|
263 // vm_ptr is coming in increasing base address order |
|
264 while (vm_ptr != NULL) { |
|
265 if (vm_ptr->is_reserved_region()) { |
|
266 // consolidate reserved memory regions for virtual memory map. |
|
267 // The criteria for consolidation is: |
|
268 // 1. two adjacent reserved memory regions |
|
269 // 2. belong to the same memory type |
|
270 // 3. reserved from the same callsite |
|
271 if (reserved_rec == NULL || |
|
272 reserved_rec->base() + reserved_rec->size() != vm_ptr->addr() || |
|
273 FLAGS_TO_MEMORY_TYPE(reserved_rec->flags()) != FLAGS_TO_MEMORY_TYPE(vm_ptr->flags()) || |
|
274 reserved_rec->pc() != vm_ptr->pc()) { |
|
275 if (!_vm_map->append(vm_ptr)) { |
229 return false; |
276 return false; |
230 } |
277 } |
231 vp = VMCallsitePointer(vptr->pc()); |
278 // inserted reserved region, we need the pointer to the element in virtual |
232 } |
279 // memory map array. |
233 vp.inc(vptr->size(), vptr->committed_size()); |
280 reserved_rec = (VMMemRegionEx*)_vm_map->at(_vm_map->length() - 1); |
234 vptr = (VMMemRegionEx*)vItr.next(); |
281 } else { |
235 } |
282 reserved_rec->expand_region(vm_ptr->addr(), vm_ptr->size()); |
236 if (vp.addr() != 0) { |
283 } |
237 if (!_vm_cs->append(&vp)) { |
284 |
|
285 if (cur_callsite != NULL && !_vm_cs->append(cur_callsite)) { |
238 return false; |
286 return false; |
239 } |
287 } |
240 } |
288 vm_callsite = VMCallsitePointer(vm_ptr->pc()); |
|
289 cur_callsite = &vm_callsite; |
|
290 vm_callsite.inc(vm_ptr->size(), 0); |
|
291 } else { |
|
292 // consolidate committed memory regions for virtual memory map |
|
293 // The criterial is: |
|
294 // 1. two adjacent committed memory regions |
|
295 // 2. committed from the same callsite |
|
296 if (committed_rec == NULL || |
|
297 committed_rec->base() + committed_rec->size() != vm_ptr->addr() || |
|
298 committed_rec->pc() != vm_ptr->pc()) { |
|
299 if (!_vm_map->append(vm_ptr)) { |
|
300 return false; |
|
301 } |
|
302 committed_rec = (VMMemRegionEx*)_vm_map->at(_vm_map->length() - 1); |
|
303 } else { |
|
304 committed_rec->expand_region(vm_ptr->addr(), vm_ptr->size()); |
|
305 } |
|
306 vm_callsite.inc(0, vm_ptr->size()); |
|
307 } |
|
308 vm_ptr = (VMMemRegionEx*)vm_itr.next(); |
|
309 } |
|
310 // deal with last record |
|
311 if (cur_callsite != NULL && !_vm_cs->append(cur_callsite)) { |
|
312 return false; |
|
313 } |
|
314 |
|
315 // sort it into callsite pc order. Details are aggregated by callsites |
|
316 _vm_cs->sort((FN_SORT)bl_vm_sort_by_pc); |
|
317 |
|
318 // walk the array to consolidate record by pc |
|
319 MemPointerArrayIteratorImpl itr(_vm_cs); |
|
320 VMCallsitePointer* callsite_rec = (VMCallsitePointer*)itr.current(); |
|
321 VMCallsitePointer* next_rec = (VMCallsitePointer*)itr.next(); |
|
322 while (next_rec != NULL) { |
|
323 assert(callsite_rec != NULL, "Sanity check"); |
|
324 if (next_rec->addr() == callsite_rec->addr()) { |
|
325 callsite_rec->inc(next_rec->reserved_amount(), next_rec->committed_amount()); |
|
326 itr.remove(); |
|
327 next_rec = (VMCallsitePointer*)itr.current(); |
|
328 } else { |
|
329 callsite_rec = next_rec; |
|
330 next_rec = (VMCallsitePointer*)itr.next(); |
|
331 } |
|
332 } |
|
333 |
241 return true; |
334 return true; |
242 } |
335 } |
243 |
336 |
244 // baseline a snapshot. If summary_only = false, memory usages aggregated by |
337 // baseline a snapshot. If summary_only = false, memory usages aggregated by |
245 // callsites are also baselined. |
338 // callsites are also baselined. |