memReporter.cpp revision 6853:91eeb8807a03
1/*
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.
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"
25
26#include "memory/allocation.hpp"
27#include "services/mallocTracker.hpp"
28#include "services/memReporter.hpp"
29#include "services/virtualMemoryTracker.hpp"
30#include "utilities/globalDefinitions.hpp"
31
32size_t MemReporterBase::reserved_total(const MallocMemory* malloc, const VirtualMemory* vm) const {
33  return malloc->malloc_size() + malloc->arena_size() + vm->reserved();
34}
35
36size_t MemReporterBase::committed_total(const MallocMemory* malloc, const VirtualMemory* vm) const {
37  return malloc->malloc_size() + malloc->arena_size() + vm->committed();
38}
39
40void MemReporterBase::print_total(size_t reserved, size_t committed) const {
41  const char* scale = current_scale();
42  output()->print("reserved=" SIZE_FORMAT "%s, committed=" SIZE_FORMAT "%s",
43    amount_in_current_scale(reserved), scale, amount_in_current_scale(committed), scale);
44}
45
46void MemReporterBase::print_malloc(size_t amount, size_t count) const {
47  const char* scale = current_scale();
48  outputStream* out = output();
49  out->print("(malloc=" SIZE_FORMAT "%s",
50    amount_in_current_scale(amount), scale);
51
52  if (count > 0) {
53    out->print(" #" SIZE_FORMAT "", count);
54  }
55
56  out->print(")");
57}
58
59void MemReporterBase::print_virtual_memory(size_t reserved, size_t committed) const {
60  const char* scale = current_scale();
61  output()->print("(mmap: reserved=" SIZE_FORMAT "%s, committed=" SIZE_FORMAT "%s)",
62    amount_in_current_scale(reserved), scale, amount_in_current_scale(committed), scale);
63}
64
65void MemReporterBase::print_malloc_line(size_t amount, size_t count) const {
66  output()->print("%28s", " ");
67  print_malloc(amount, count);
68  output()->print_cr(" ");
69}
70
71void MemReporterBase::print_virtual_memory_line(size_t reserved, size_t committed) const {
72  output()->print("%28s", " ");
73  print_virtual_memory(reserved, committed);
74  output()->print_cr(" ");
75}
76
77void MemReporterBase::print_arena_line(size_t amount, size_t count) const {
78  const char* scale = current_scale();
79  output()->print_cr("%27s (arena=" SIZE_FORMAT "%s #" SIZE_FORMAT ")", " ",
80    amount_in_current_scale(amount), scale, count);
81}
82
83void MemReporterBase::print_virtual_memory_region(const char* type, address base, size_t size) const {
84  const char* scale = current_scale();
85  output()->print("[" PTR_FORMAT " - " PTR_FORMAT "] %s " SIZE_FORMAT "%s",
86    p2i(base), p2i(base + size), type, amount_in_current_scale(size), scale);
87}
88
89
90void MemSummaryReporter::report() {
91  const char* scale = current_scale();
92  outputStream* out = output();
93  size_t total_reserved_amount = _malloc_snapshot->total() +
94    _vm_snapshot->total_reserved();
95  size_t total_committed_amount = _malloc_snapshot->total() +
96    _vm_snapshot->total_committed();
97
98  // Overall total
99  out->print_cr("\nNative Memory Tracking:\n");
100  out->print("Total: ");
101  print_total(total_reserved_amount, total_committed_amount);
102  out->print("\n");
103
104  // Summary by memory type
105  for (int index = 0; index < mt_number_of_types; index ++) {
106    MEMFLAGS flag = NMTUtil::index_to_flag(index);
107    // thread stack is reported as part of thread category
108    if (flag == mtThreadStack) continue;
109    MallocMemory* malloc_memory = _malloc_snapshot->by_type(flag);
110    VirtualMemory* virtual_memory = _vm_snapshot->by_type(flag);
111
112    report_summary_of_type(flag, malloc_memory, virtual_memory);
113  }
114}
115
116void MemSummaryReporter::report_summary_of_type(MEMFLAGS flag,
117  MallocMemory*  malloc_memory, VirtualMemory* virtual_memory) {
118
119  size_t reserved_amount  = reserved_total (malloc_memory, virtual_memory);
120  size_t committed_amount = committed_total(malloc_memory, virtual_memory);
121
122  // Count thread's native stack in "Thread" category
123  if (flag == mtThread) {
124    const VirtualMemory* thread_stack_usage =
125      (const VirtualMemory*)_vm_snapshot->by_type(mtThreadStack);
126    reserved_amount  += thread_stack_usage->reserved();
127    committed_amount += thread_stack_usage->committed();
128  } else if (flag == mtNMT) {
129    // Count malloc headers in "NMT" category
130    reserved_amount  += _malloc_snapshot->malloc_overhead()->size();
131    committed_amount += _malloc_snapshot->malloc_overhead()->size();
132  }
133
134  if (amount_in_current_scale(reserved_amount) > 0) {
135    outputStream* out   = output();
136    const char*   scale = current_scale();
137    out->print("-%26s (", NMTUtil::flag_to_name(flag));
138    print_total(reserved_amount, committed_amount);
139    out->print_cr(")");
140
141    if (flag == mtClass) {
142      // report class count
143      out->print_cr("%27s (classes #" SIZE_FORMAT ")", " ", _class_count);
144    } else if (flag == mtThread) {
145      // report thread count
146      out->print_cr("%27s (thread #" SIZE_FORMAT ")", " ", _malloc_snapshot->thread_count());
147      const VirtualMemory* thread_stack_usage =
148       _vm_snapshot->by_type(mtThreadStack);
149      out->print("%27s (stack: ", " ");
150      print_total(thread_stack_usage->reserved(), thread_stack_usage->committed());
151      out->print_cr(")");
152    }
153
154     // report malloc'd memory
155    if (amount_in_current_scale(malloc_memory->malloc_size()) > 0) {
156      // We don't know how many arena chunks are in used, so don't report the count
157      size_t count = (flag == mtChunk) ? 0 : malloc_memory->malloc_count();
158      print_malloc_line(malloc_memory->malloc_size(), count);
159    }
160
161    if (amount_in_current_scale(virtual_memory->reserved()) > 0) {
162      print_virtual_memory_line(virtual_memory->reserved(), virtual_memory->committed());
163    }
164
165    if (amount_in_current_scale(malloc_memory->arena_size()) > 0) {
166      print_arena_line(malloc_memory->arena_size(), malloc_memory->arena_count());
167    }
168
169    if (flag == mtNMT &&
170      amount_in_current_scale(_malloc_snapshot->malloc_overhead()->size()) > 0) {
171      out->print_cr("%27s (tracking overhead=" SIZE_FORMAT "%s)", " ",
172        amount_in_current_scale(_malloc_snapshot->malloc_overhead()->size()), scale);
173    }
174
175    out->print_cr(" ");
176  }
177}
178
179void MemDetailReporter::report_detail() {
180  // Start detail report
181  outputStream* out = output();
182  out->print_cr("Details:\n");
183
184  report_malloc_sites();
185  report_virtual_memory_allocation_sites();
186}
187
188void MemDetailReporter::report_malloc_sites() {
189  MallocSiteIterator         malloc_itr = _baseline.malloc_sites(MemBaseline::by_size);
190  if (malloc_itr.is_empty()) return;
191
192  outputStream* out = output();
193
194  const MallocSite* malloc_site;
195  while ((malloc_site = malloc_itr.next()) != NULL) {
196    // Don't report if size is too small
197    if (amount_in_current_scale(malloc_site->size()) == 0)
198      continue;
199
200    const NativeCallStack* stack = malloc_site->call_stack();
201    stack->print_on(out);
202    out->print("%29s", " ");
203    print_malloc(malloc_site->size(), malloc_site->count());
204    out->print_cr("\n");
205  }
206}
207
208void MemDetailReporter::report_virtual_memory_allocation_sites()  {
209  VirtualMemorySiteIterator  virtual_memory_itr =
210    _baseline.virtual_memory_sites(MemBaseline::by_size);
211
212  if (virtual_memory_itr.is_empty()) return;
213
214  outputStream* out = output();
215  const VirtualMemoryAllocationSite*  virtual_memory_site;
216
217  while ((virtual_memory_site = virtual_memory_itr.next()) != NULL) {
218    // Don't report if size is too small
219    if (amount_in_current_scale(virtual_memory_site->reserved()) == 0)
220      continue;
221
222    const NativeCallStack* stack = virtual_memory_site->call_stack();
223    stack->print_on(out);
224    out->print("%28s (", " ");
225    print_total(virtual_memory_site->reserved(), virtual_memory_site->committed());
226    out->print_cr(")\n");
227  }
228}
229
230
231void MemDetailReporter::report_virtual_memory_map() {
232  // Virtual memory map always in base address order
233  VirtualMemoryAllocationIterator itr = _baseline.virtual_memory_allocations();
234  const ReservedMemoryRegion* rgn;
235
236  output()->print_cr("Virtual memory map:");
237  while ((rgn = itr.next()) != NULL) {
238    report_virtual_memory_region(rgn);
239  }
240}
241
242void MemDetailReporter::report_virtual_memory_region(const ReservedMemoryRegion* reserved_rgn) {
243  assert(reserved_rgn != NULL, "NULL pointer");
244
245  // Don't report if size is too small
246  if (amount_in_current_scale(reserved_rgn->size()) == 0) return;
247
248  outputStream* out = output();
249  const char* scale = current_scale();
250  const NativeCallStack*  stack = reserved_rgn->call_stack();
251  bool all_committed = reserved_rgn->all_committed();
252  const char* region_type = (all_committed ? "reserved and committed" : "reserved");
253  out->print_cr(" ");
254  print_virtual_memory_region(region_type, reserved_rgn->base(), reserved_rgn->size());
255  out->print(" for %s", NMTUtil::flag_to_name(reserved_rgn->flag()));
256  if (stack->is_empty()) {
257    out->print_cr(" ");
258  } else {
259    out->print_cr(" from");
260    stack->print_on(out, 4);
261  }
262
263  if (all_committed) return;
264
265  CommittedRegionIterator itr = reserved_rgn->iterate_committed_regions();
266  const CommittedMemoryRegion* committed_rgn;
267  while ((committed_rgn = itr.next()) != NULL) {
268    // Don't report if size is too small
269    if (amount_in_current_scale(committed_rgn->size()) == 0) continue;
270    stack = committed_rgn->call_stack();
271    out->print("\n\t");
272    print_virtual_memory_region("committed", committed_rgn->base(), committed_rgn->size());
273    if (stack->is_empty()) {
274      out->print_cr(" ");
275    } else {
276      out->print_cr(" from");
277      stack->print_on(out, 12);
278    }
279  }
280}
281
282void MemSummaryDiffReporter::report_diff() {
283  const char* scale = current_scale();
284  outputStream* out = output();
285  out->print_cr("\nNative Memory Tracking:\n");
286
287  // Overall diff
288  out->print("Total: ");
289  print_virtual_memory_diff(_current_baseline.total_reserved_memory(),
290    _current_baseline.total_committed_memory(), _early_baseline.total_reserved_memory(),
291    _early_baseline.total_committed_memory());
292
293  out->print_cr("\n");
294
295  // Summary diff by memory type
296  for (int index = 0; index < mt_number_of_types; index ++) {
297    MEMFLAGS flag = NMTUtil::index_to_flag(index);
298    // thread stack is reported as part of thread category
299    if (flag == mtThreadStack) continue;
300    diff_summary_of_type(flag, _early_baseline.malloc_memory(flag),
301      _early_baseline.virtual_memory(flag), _current_baseline.malloc_memory(flag),
302      _current_baseline.virtual_memory(flag));
303  }
304}
305
306void MemSummaryDiffReporter::print_malloc_diff(size_t current_amount, size_t current_count,
307    size_t early_amount, size_t early_count) const {
308  const char* scale = current_scale();
309  outputStream* out = output();
310
311  out->print("malloc=" SIZE_FORMAT "%s", amount_in_current_scale(current_amount), scale);
312  long amount_diff = diff_in_current_scale(current_amount, early_amount);
313  if (amount_diff != 0) {
314    out->print(" %+ld%s", amount_diff, scale);
315  }
316  if (current_count > 0) {
317    out->print(" #" SIZE_FORMAT "", current_count);
318    if (current_count != early_count) {
319      out->print(" %+d", (int)(current_count - early_count));
320    }
321  }
322}
323
324void MemSummaryDiffReporter::print_arena_diff(size_t current_amount, size_t current_count,
325  size_t early_amount, size_t early_count) const {
326  const char* scale = current_scale();
327  outputStream* out = output();
328  out->print("arena=" SIZE_FORMAT "%s", amount_in_current_scale(current_amount), scale);
329  if (diff_in_current_scale(current_amount, early_amount) != 0) {
330    out->print(" %+ld", diff_in_current_scale(current_amount, early_amount));
331  }
332
333  out->print(" #" SIZE_FORMAT "", current_count);
334  if (current_count != early_count) {
335    out->print(" %+d", (int)(current_count - early_count));
336  }
337}
338
339void MemSummaryDiffReporter::print_virtual_memory_diff(size_t current_reserved, size_t current_committed,
340    size_t early_reserved, size_t early_committed) const {
341  const char* scale = current_scale();
342  outputStream* out = output();
343  out->print("reserved=" SIZE_FORMAT "%s", amount_in_current_scale(current_reserved), scale);
344  long reserved_diff = diff_in_current_scale(current_reserved, early_reserved);
345  if (reserved_diff != 0) {
346    out->print(" %+ld%s", reserved_diff, scale);
347  }
348
349  out->print(", committed=" SIZE_FORMAT "%s", amount_in_current_scale(current_committed), scale);
350  long committed_diff = diff_in_current_scale(current_committed, early_committed);
351  if (committed_diff != 0) {
352    out->print(" %+ld%s", committed_diff, scale);
353  }
354}
355
356
357void MemSummaryDiffReporter::diff_summary_of_type(MEMFLAGS flag, const MallocMemory* early_malloc,
358  const VirtualMemory* early_vm, const MallocMemory* current_malloc,
359  const VirtualMemory* current_vm) const {
360
361  outputStream* out = output();
362  const char* scale = current_scale();
363
364  // Total reserved and committed memory in current baseline
365  size_t current_reserved_amount  = reserved_total (current_malloc, current_vm);
366  size_t current_committed_amount = committed_total(current_malloc, current_vm);
367
368  // Total reserved and committed memory in early baseline
369  size_t early_reserved_amount  = reserved_total(early_malloc, early_vm);
370  size_t early_committed_amount = committed_total(early_malloc, early_vm);
371
372  // Adjust virtual memory total
373  if (flag == mtThread) {
374    const VirtualMemory* early_thread_stack_usage =
375      _early_baseline.virtual_memory(mtThreadStack);
376    const VirtualMemory* current_thread_stack_usage =
377      _current_baseline.virtual_memory(mtThreadStack);
378
379    early_reserved_amount  += early_thread_stack_usage->reserved();
380    early_committed_amount += early_thread_stack_usage->committed();
381
382    current_reserved_amount  += current_thread_stack_usage->reserved();
383    current_committed_amount += current_thread_stack_usage->committed();
384  } else if (flag == mtNMT) {
385    early_reserved_amount  += _early_baseline.malloc_tracking_overhead();
386    early_committed_amount += _early_baseline.malloc_tracking_overhead();
387
388    current_reserved_amount  += _current_baseline.malloc_tracking_overhead();
389    current_committed_amount += _current_baseline.malloc_tracking_overhead();
390  }
391
392  if (amount_in_current_scale(current_reserved_amount) > 0 ||
393      diff_in_current_scale(current_reserved_amount, early_reserved_amount) != 0) {
394
395    // print summary line
396    out->print("-%26s (", NMTUtil::flag_to_name(flag));
397    print_virtual_memory_diff(current_reserved_amount, current_committed_amount,
398      early_reserved_amount, early_committed_amount);
399    out->print_cr(")");
400
401    // detail lines
402    if (flag == mtClass) {
403      // report class count
404      out->print("%27s (classes #" SIZE_FORMAT "", " ", _current_baseline.class_count());
405      int class_count_diff = (int)(_current_baseline.class_count() -
406        _early_baseline.class_count());
407      if (_current_baseline.class_count() != _early_baseline.class_count()) {
408        out->print(" %+d", (int)(_current_baseline.class_count() - _early_baseline.class_count()));
409      }
410      out->print_cr(")");
411    } else if (flag == mtThread) {
412      // report thread count
413      out->print("%27s (thread #" SIZE_FORMAT "", " ", _current_baseline.thread_count());
414      int thread_count_diff = (int)(_current_baseline.thread_count() -
415          _early_baseline.thread_count());
416      if (thread_count_diff != 0) {
417        out->print(" %+d", thread_count_diff);
418      }
419      out->print_cr(")");
420
421      // report thread stack
422      const VirtualMemory* current_thread_stack =
423          _current_baseline.virtual_memory(mtThreadStack);
424      const VirtualMemory* early_thread_stack =
425        _early_baseline.virtual_memory(mtThreadStack);
426
427      out->print("%27s (stack: ", " ");
428      print_virtual_memory_diff(current_thread_stack->reserved(), current_thread_stack->committed(),
429        early_thread_stack->reserved(), early_thread_stack->committed());
430      out->print_cr(")");
431    }
432
433    // Report malloc'd memory
434    size_t current_malloc_amount = current_malloc->malloc_size();
435    size_t early_malloc_amount   = early_malloc->malloc_size();
436    if (amount_in_current_scale(current_malloc_amount) > 0 ||
437        diff_in_current_scale(current_malloc_amount, early_malloc_amount) != 0) {
438      out->print("%28s(", " ");
439      print_malloc_diff(current_malloc_amount, (flag == mtChunk) ? 0 : current_malloc->malloc_count(),
440        early_malloc_amount, early_malloc->malloc_count());
441      out->print_cr(")");
442    }
443
444    // Report virtual memory
445    if (amount_in_current_scale(current_vm->reserved()) > 0 ||
446        diff_in_current_scale(current_vm->reserved(), early_vm->reserved()) != 0) {
447      out->print("%27s (mmap: ", " ");
448      print_virtual_memory_diff(current_vm->reserved(), current_vm->committed(),
449        early_vm->reserved(), early_vm->committed());
450      out->print_cr(")");
451    }
452
453    // Report arena memory
454    if (amount_in_current_scale(current_malloc->arena_size()) > 0 ||
455        diff_in_current_scale(current_malloc->arena_size(), early_malloc->arena_size()) != 0) {
456      out->print("%28s(", " ");
457      print_arena_diff(current_malloc->arena_size(), current_malloc->arena_count(),
458        early_malloc->arena_size(), early_malloc->arena_count());
459      out->print_cr(")");
460    }
461
462    // Report native memory tracking overhead
463    if (flag == mtNMT) {
464      size_t current_tracking_overhead = amount_in_current_scale(_current_baseline.malloc_tracking_overhead());
465      size_t early_tracking_overhead   = amount_in_current_scale(_early_baseline.malloc_tracking_overhead());
466
467      out->print("%27s (tracking overhead=" SIZE_FORMAT "%s", " ",
468        amount_in_current_scale(_current_baseline.malloc_tracking_overhead()), scale);
469
470      long overhead_diff = diff_in_current_scale(_current_baseline.malloc_tracking_overhead(),
471           _early_baseline.malloc_tracking_overhead());
472      if (overhead_diff != 0) {
473        out->print(" %+ld%s", overhead_diff, scale);
474      }
475      out->print_cr(")");
476    }
477    out->print_cr(" ");
478  }
479}
480
481void MemDetailDiffReporter::report_diff() {
482  MemSummaryDiffReporter::report_diff();
483  diff_malloc_sites();
484  diff_virtual_memory_sites();
485}
486
487void MemDetailDiffReporter::diff_malloc_sites() const {
488  MallocSiteIterator early_itr = _early_baseline.malloc_sites(MemBaseline::by_site);
489  MallocSiteIterator current_itr = _current_baseline.malloc_sites(MemBaseline::by_site);
490
491  const MallocSite* early_site   = early_itr.next();
492  const MallocSite* current_site = current_itr.next();
493
494  while (early_site != NULL || current_site != NULL) {
495    if (early_site == NULL) {
496      new_malloc_site(current_site);
497      current_site = current_itr.next();
498    } else if (current_site == NULL) {
499      old_malloc_site(early_site);
500      early_site = early_itr.next();
501    } else {
502      int compVal = current_site->call_stack()->compare(*early_site->call_stack());
503      if (compVal < 0) {
504        new_malloc_site(current_site);
505        current_site = current_itr.next();
506      } else if (compVal > 0) {
507        old_malloc_site(early_site);
508        early_site = early_itr.next();
509      } else {
510        diff_malloc_site(early_site, current_site);
511        early_site   = early_itr.next();
512        current_site = current_itr.next();
513      }
514    }
515  }
516}
517
518void MemDetailDiffReporter::diff_virtual_memory_sites() const {
519  VirtualMemorySiteIterator early_itr = _early_baseline.virtual_memory_sites(MemBaseline::by_site);
520  VirtualMemorySiteIterator current_itr = _current_baseline.virtual_memory_sites(MemBaseline::by_site);
521
522  const VirtualMemoryAllocationSite* early_site   = early_itr.next();
523  const VirtualMemoryAllocationSite* current_site = current_itr.next();
524
525  while (early_site != NULL || current_site != NULL) {
526    if (early_site == NULL) {
527      new_virtual_memory_site(current_site);
528      current_site = current_itr.next();
529    } else if (current_site == NULL) {
530      old_virtual_memory_site(early_site);
531      early_site = early_itr.next();
532    } else {
533      int compVal = current_site->call_stack()->compare(*early_site->call_stack());
534      if (compVal < 0) {
535        new_virtual_memory_site(current_site);
536        current_site = current_itr.next();
537      } else if (compVal > 0) {
538        old_virtual_memory_site(early_site);
539        early_site = early_itr.next();
540      } else {
541        diff_virtual_memory_site(early_site, current_site);
542        early_site   = early_itr.next();
543        current_site = current_itr.next();
544      }
545    }
546  }
547}
548
549
550void MemDetailDiffReporter::new_malloc_site(const MallocSite* malloc_site) const {
551  diff_malloc_site(malloc_site->call_stack(), malloc_site->size(), malloc_site->count(),
552    0, 0);
553}
554
555void MemDetailDiffReporter::old_malloc_site(const MallocSite* malloc_site) const {
556  diff_malloc_site(malloc_site->call_stack(), 0, 0, malloc_site->size(),
557    malloc_site->count());
558}
559
560void MemDetailDiffReporter::diff_malloc_site(const MallocSite* early,
561  const MallocSite* current)  const {
562  diff_malloc_site(current->call_stack(), current->size(), current->count(),
563    early->size(), early->count());
564}
565
566void MemDetailDiffReporter::diff_malloc_site(const NativeCallStack* stack, size_t current_size,
567  size_t current_count, size_t early_size, size_t early_count) const {
568  outputStream* out = output();
569
570  assert(stack != NULL, "NULL stack");
571
572  if (diff_in_current_scale(current_size, early_size) == 0) {
573      return;
574  }
575
576  stack->print_on(out);
577  out->print("%28s (", " ");
578  print_malloc_diff(current_size, current_count,
579    early_size, early_count);
580
581  out->print_cr(")\n");
582}
583
584
585void MemDetailDiffReporter::new_virtual_memory_site(const VirtualMemoryAllocationSite* site) const {
586  diff_virtual_memory_site(site->call_stack(), site->reserved(), site->committed(), 0, 0);
587}
588
589void MemDetailDiffReporter::old_virtual_memory_site(const VirtualMemoryAllocationSite* site) const {
590  diff_virtual_memory_site(site->call_stack(), 0, 0, site->reserved(), site->committed());
591}
592
593void MemDetailDiffReporter::diff_virtual_memory_site(const VirtualMemoryAllocationSite* early,
594  const VirtualMemoryAllocationSite* current) const {
595  diff_virtual_memory_site(current->call_stack(), current->reserved(), current->committed(),
596    early->reserved(), early->committed());
597}
598
599void MemDetailDiffReporter::diff_virtual_memory_site(const NativeCallStack* stack, size_t current_reserved,
600  size_t current_committed, size_t early_reserved, size_t early_committed) const  {
601  outputStream* out = output();
602
603  // no change
604  if (diff_in_current_scale(current_reserved, early_reserved) == 0 &&
605      diff_in_current_scale(current_committed, early_committed) == 0) {
606    return;
607  }
608
609  stack->print_on(out);
610  out->print("%28s (mmap: ", " ");
611  print_virtual_memory_diff(current_reserved, current_committed,
612    early_reserved, early_committed);
613
614  out->print_cr(")\n");
615 }
616
617