src/hotspot/share/gc/z/zStat.cpp
changeset 50525 767cdb97f103
child 50812 0d813fbd94ed
equal deleted inserted replaced
50524:04f4e983c2f7 50525:767cdb97f103
       
     1 /*
       
     2  * Copyright (c) 2015, 2018, 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 #include "gc/z/zCollectedHeap.hpp"
       
    26 #include "gc/z/zCPU.hpp"
       
    27 #include "gc/z/zGlobals.hpp"
       
    28 #include "gc/z/zHeap.inline.hpp"
       
    29 #include "gc/z/zLargePages.inline.hpp"
       
    30 #include "gc/z/zNMethodTable.hpp"
       
    31 #include "gc/z/zNUMA.hpp"
       
    32 #include "gc/z/zStat.hpp"
       
    33 #include "gc/z/zTracer.inline.hpp"
       
    34 #include "gc/z/zUtils.hpp"
       
    35 #include "memory/resourceArea.hpp"
       
    36 #include "runtime/atomic.hpp"
       
    37 #include "runtime/os.hpp"
       
    38 #include "runtime/timer.hpp"
       
    39 #include "utilities/align.hpp"
       
    40 #include "utilities/compilerWarnings.hpp"
       
    41 #include "utilities/debug.hpp"
       
    42 #include "utilities/ticks.hpp"
       
    43 
       
    44 //
       
    45 // Stat sampler/counter data
       
    46 //
       
    47 struct ZStatSamplerData {
       
    48   uint64_t _nsamples;
       
    49   uint64_t _sum;
       
    50   uint64_t _max;
       
    51 
       
    52   ZStatSamplerData() :
       
    53     _nsamples(0),
       
    54     _sum(0),
       
    55     _max(0) {}
       
    56 
       
    57   void add(const ZStatSamplerData& new_sample) {
       
    58     _nsamples += new_sample._nsamples;
       
    59     _sum += new_sample._nsamples;
       
    60     _max = MAX2(_max, new_sample._max);
       
    61   }
       
    62 };
       
    63 
       
    64 struct ZStatCounterData {
       
    65   uint64_t _counter;
       
    66 
       
    67   ZStatCounterData() :
       
    68     _counter(0) {}
       
    69 };
       
    70 
       
    71 //
       
    72 // Stat sampler history
       
    73 //
       
    74 template <size_t size>
       
    75 class ZStatSamplerHistoryInterval {
       
    76 private:
       
    77   size_t           _next;
       
    78   ZStatSamplerData _samples[size];
       
    79   ZStatSamplerData _accumulated;
       
    80   ZStatSamplerData _total;
       
    81 
       
    82 public:
       
    83   ZStatSamplerHistoryInterval() :
       
    84       _next(0),
       
    85       _samples(),
       
    86       _total(),
       
    87       _accumulated() {}
       
    88 
       
    89   bool add(const ZStatSamplerData& new_sample) {
       
    90     // Insert sample
       
    91     const ZStatSamplerData old_sample = _samples[_next];
       
    92     _samples[_next] = new_sample;
       
    93 
       
    94     // Adjust accumulated
       
    95     _accumulated._nsamples += new_sample._nsamples;
       
    96     _accumulated._sum += new_sample._sum;
       
    97     _accumulated._max = MAX2(_accumulated._max, new_sample._max);
       
    98 
       
    99     // Adjust total
       
   100     _total._nsamples -= old_sample._nsamples;
       
   101     _total._sum -= old_sample._sum;
       
   102     _total._nsamples += new_sample._nsamples;
       
   103     _total._sum += new_sample._sum;
       
   104     if (_total._max < new_sample._max) {
       
   105       // Found new max
       
   106       _total._max = new_sample._max;
       
   107     } else if (_total._max == old_sample._max) {
       
   108       // Removed old max, reset and find new max
       
   109       _total._max = 0;
       
   110       for (size_t i = 0; i < size; i++) {
       
   111         if (_total._max < _samples[i]._max) {
       
   112           _total._max = _samples[i]._max;
       
   113         }
       
   114       }
       
   115     }
       
   116 
       
   117     // Adjust next
       
   118     if (++_next == size) {
       
   119       _next = 0;
       
   120 
       
   121       // Clear accumulated
       
   122       const ZStatSamplerData zero;
       
   123       _accumulated = zero;
       
   124 
       
   125       // Became full
       
   126       return true;
       
   127     }
       
   128 
       
   129     // Not yet full
       
   130     return false;
       
   131   }
       
   132 
       
   133   const ZStatSamplerData& total() const {
       
   134     return _total;
       
   135   }
       
   136 
       
   137   const ZStatSamplerData& accumulated() const {
       
   138     return _accumulated;
       
   139   }
       
   140 };
       
   141 
       
   142 class ZStatSamplerHistory : public CHeapObj<mtGC> {
       
   143 private:
       
   144   ZStatSamplerHistoryInterval<10> _10seconds;
       
   145   ZStatSamplerHistoryInterval<60> _10minutes;
       
   146   ZStatSamplerHistoryInterval<60> _10hours;
       
   147   ZStatSamplerData                _total;
       
   148 
       
   149   uint64_t avg(uint64_t sum, uint64_t nsamples) const {
       
   150     return (nsamples > 0) ? sum / nsamples : 0;
       
   151   }
       
   152 
       
   153 public:
       
   154   ZStatSamplerHistory() :
       
   155       _10seconds(),
       
   156       _10minutes(),
       
   157       _10hours(),
       
   158       _total() {}
       
   159 
       
   160   void add(const ZStatSamplerData& new_sample) {
       
   161     if (_10seconds.add(new_sample)) {
       
   162       if (_10minutes.add(_10seconds.total())) {
       
   163         if (_10hours.add(_10minutes.total())) {
       
   164           _total.add(_10hours.total());
       
   165         }
       
   166       }
       
   167     }
       
   168   }
       
   169 
       
   170   uint64_t avg_10_seconds() const {
       
   171     const uint64_t sum      = _10seconds.total()._sum;
       
   172     const uint64_t nsamples = _10seconds.total()._nsamples;
       
   173     return avg(sum, nsamples);
       
   174   }
       
   175 
       
   176   uint64_t avg_10_minutes() const {
       
   177     const uint64_t sum      = _10seconds.accumulated()._sum +
       
   178                               _10minutes.total()._sum;
       
   179     const uint64_t nsamples = _10seconds.accumulated()._nsamples +
       
   180                               _10minutes.total()._nsamples;
       
   181     return avg(sum, nsamples);
       
   182   }
       
   183 
       
   184   uint64_t avg_10_hours() const {
       
   185     const uint64_t sum      = _10seconds.accumulated()._sum +
       
   186                               _10minutes.accumulated()._sum +
       
   187                               _10hours.total()._sum;
       
   188     const uint64_t nsamples = _10seconds.accumulated()._nsamples +
       
   189                               _10minutes.accumulated()._nsamples +
       
   190                               _10hours.total()._nsamples;
       
   191     return avg(sum, nsamples);
       
   192   }
       
   193 
       
   194   uint64_t avg_total() const {
       
   195     const uint64_t sum      = _10seconds.accumulated()._sum +
       
   196                               _10minutes.accumulated()._sum +
       
   197                               _10hours.accumulated()._sum +
       
   198                               _total._sum;
       
   199     const uint64_t nsamples = _10seconds.accumulated()._nsamples +
       
   200                               _10minutes.accumulated()._nsamples +
       
   201                               _10hours.accumulated()._nsamples +
       
   202                               _total._nsamples;
       
   203     return avg(sum, nsamples);
       
   204   }
       
   205 
       
   206   uint64_t max_10_seconds() const {
       
   207     return _10seconds.total()._max;
       
   208   }
       
   209 
       
   210   uint64_t max_10_minutes() const {
       
   211     return MAX2(_10seconds.accumulated()._max,
       
   212                 _10minutes.total()._max);
       
   213   }
       
   214 
       
   215   uint64_t max_10_hours() const {
       
   216     return MAX3(_10seconds.accumulated()._max,
       
   217                 _10minutes.accumulated()._max,
       
   218                 _10hours.total()._max);
       
   219   }
       
   220 
       
   221   uint64_t max_total() const {
       
   222     return MAX4(_10seconds.accumulated()._max,
       
   223                 _10minutes.accumulated()._max,
       
   224                 _10hours.accumulated()._max,
       
   225                 _total._max);
       
   226   }
       
   227 };
       
   228 
       
   229 //
       
   230 // Stat unit printers
       
   231 //
       
   232 void ZStatUnitTime(LogTargetHandle log, const ZStatSampler& sampler, const ZStatSamplerHistory& history) {
       
   233   log.print(" %10s: %-40s  "
       
   234             "%9.3f / %-9.3f "
       
   235             "%9.3f / %-9.3f "
       
   236             "%9.3f / %-9.3f "
       
   237             "%9.3f / %-9.3f   ms",
       
   238             sampler.group(),
       
   239             sampler.name(),
       
   240             TimeHelper::counter_to_millis(history.avg_10_seconds()),
       
   241             TimeHelper::counter_to_millis(history.max_10_seconds()),
       
   242             TimeHelper::counter_to_millis(history.avg_10_minutes()),
       
   243             TimeHelper::counter_to_millis(history.max_10_minutes()),
       
   244             TimeHelper::counter_to_millis(history.avg_10_hours()),
       
   245             TimeHelper::counter_to_millis(history.max_10_hours()),
       
   246             TimeHelper::counter_to_millis(history.avg_total()),
       
   247             TimeHelper::counter_to_millis(history.max_total()));
       
   248 }
       
   249 
       
   250 void ZStatUnitBytes(LogTargetHandle log, const ZStatSampler& sampler, const ZStatSamplerHistory& history) {
       
   251   log.print(" %10s: %-40s  "
       
   252             UINT64_FORMAT_W(9) " / " UINT64_FORMAT_W(-9) " "
       
   253             UINT64_FORMAT_W(9) " / " UINT64_FORMAT_W(-9) " "
       
   254             UINT64_FORMAT_W(9) " / " UINT64_FORMAT_W(-9) " "
       
   255             UINT64_FORMAT_W(9) " / " UINT64_FORMAT_W(-9) "   MB",
       
   256             sampler.group(),
       
   257             sampler.name(),
       
   258             history.avg_10_seconds() / M,
       
   259             history.max_10_seconds() / M,
       
   260             history.avg_10_minutes() / M,
       
   261             history.max_10_minutes() / M,
       
   262             history.avg_10_hours() / M,
       
   263             history.max_10_hours() / M,
       
   264             history.avg_total() / M,
       
   265             history.max_total() / M);
       
   266 }
       
   267 
       
   268 void ZStatUnitThreads(LogTargetHandle log, const ZStatSampler& sampler, const ZStatSamplerHistory& history) {
       
   269   log.print(" %10s: %-40s  "
       
   270             UINT64_FORMAT_W(9) " / " UINT64_FORMAT_W(-9) " "
       
   271             UINT64_FORMAT_W(9) " / " UINT64_FORMAT_W(-9) " "
       
   272             UINT64_FORMAT_W(9) " / " UINT64_FORMAT_W(-9) " "
       
   273             UINT64_FORMAT_W(9) " / " UINT64_FORMAT_W(-9) "   threads",
       
   274             sampler.group(),
       
   275             sampler.name(),
       
   276             history.avg_10_seconds(),
       
   277             history.max_10_seconds(),
       
   278             history.avg_10_minutes(),
       
   279             history.max_10_minutes(),
       
   280             history.avg_10_hours(),
       
   281             history.max_10_hours(),
       
   282             history.avg_total(),
       
   283             history.max_total());
       
   284 }
       
   285 
       
   286 void ZStatUnitBytesPerSecond(LogTargetHandle log, const ZStatSampler& sampler, const ZStatSamplerHistory& history) {
       
   287   log.print(" %10s: %-40s  "
       
   288             UINT64_FORMAT_W(9) " / " UINT64_FORMAT_W(-9) " "
       
   289             UINT64_FORMAT_W(9) " / " UINT64_FORMAT_W(-9) " "
       
   290             UINT64_FORMAT_W(9) " / " UINT64_FORMAT_W(-9) " "
       
   291             UINT64_FORMAT_W(9) " / " UINT64_FORMAT_W(-9) "   MB/s",
       
   292             sampler.group(),
       
   293             sampler.name(),
       
   294             history.avg_10_seconds() / M,
       
   295             history.max_10_seconds() / M,
       
   296             history.avg_10_minutes() / M,
       
   297             history.max_10_minutes() / M,
       
   298             history.avg_10_hours() / M,
       
   299             history.max_10_hours() / M,
       
   300             history.avg_total() / M,
       
   301             history.max_total() / M);
       
   302 }
       
   303 
       
   304 void ZStatUnitOpsPerSecond(LogTargetHandle log, const ZStatSampler& sampler, const ZStatSamplerHistory& history) {
       
   305   log.print(" %10s: %-40s  "
       
   306             UINT64_FORMAT_W(9) " / " UINT64_FORMAT_W(-9) " "
       
   307             UINT64_FORMAT_W(9) " / " UINT64_FORMAT_W(-9) " "
       
   308             UINT64_FORMAT_W(9) " / " UINT64_FORMAT_W(-9) " "
       
   309             UINT64_FORMAT_W(9) " / " UINT64_FORMAT_W(-9) "   ops/s",
       
   310             sampler.group(),
       
   311             sampler.name(),
       
   312             history.avg_10_seconds(),
       
   313             history.max_10_seconds(),
       
   314             history.avg_10_minutes(),
       
   315             history.max_10_minutes(),
       
   316             history.avg_10_hours(),
       
   317             history.max_10_hours(),
       
   318             history.avg_total(),
       
   319             history.max_total());
       
   320 }
       
   321 
       
   322 //
       
   323 // Stat value
       
   324 //
       
   325 uintptr_t ZStatValue::_base = 0;
       
   326 uint32_t  ZStatValue::_cpu_offset = 0;
       
   327 
       
   328 ZStatValue::ZStatValue(const char* group,
       
   329                           const char* name,
       
   330                           uint32_t id,
       
   331                           uint32_t size) :
       
   332     _group(group),
       
   333     _name(name),
       
   334     _id(id),
       
   335     _offset(_cpu_offset) {
       
   336   assert(_base == 0, "Already initialized");
       
   337   _cpu_offset += size;
       
   338 }
       
   339 
       
   340 template <typename T>
       
   341 T* ZStatValue::get_cpu_local(uint32_t cpu) const {
       
   342   assert(_base != 0, "Not initialized");
       
   343   const uintptr_t cpu_base = _base + (_cpu_offset * cpu);
       
   344   const uintptr_t value_addr = cpu_base + _offset;
       
   345   return (T*)value_addr;
       
   346 }
       
   347 
       
   348 void ZStatValue::initialize() {
       
   349   // Finalize and align CPU offset
       
   350   _cpu_offset = align_up(_cpu_offset, ZCacheLineSize);
       
   351 
       
   352   // Allocation aligned memory
       
   353   const size_t size = _cpu_offset * ZCPU::count();
       
   354   _base = ZUtils::alloc_aligned(ZCacheLineSize, size);
       
   355   memset((void*)_base, 0, size);
       
   356 }
       
   357 
       
   358 const char* ZStatValue::group() const {
       
   359   return _group;
       
   360 }
       
   361 
       
   362 const char* ZStatValue::name() const {
       
   363   return _name;
       
   364 }
       
   365 
       
   366 uint32_t ZStatValue::id() const {
       
   367   return _id;
       
   368 }
       
   369 
       
   370 //
       
   371 // Stat iterable value
       
   372 //
       
   373 template <typename T> uint32_t ZStatIterableValue<T>::_count = 0;
       
   374 template <typename T> T*       ZStatIterableValue<T>::_first = NULL;
       
   375 
       
   376 template <typename T>
       
   377 ZStatIterableValue<T>::ZStatIterableValue(const char* group,
       
   378                                           const char* name,
       
   379                                           uint32_t size) :
       
   380     ZStatValue(group, name, _count++, size),
       
   381     _next(insert()) {}
       
   382 
       
   383 template <typename T>
       
   384 T* ZStatIterableValue<T>::insert() const {
       
   385   T** current = &_first;
       
   386 
       
   387   while (*current != NULL) {
       
   388     // First sort by group, then by name
       
   389     const int group_cmp = strcmp((*current)->group(), group());
       
   390     const int name_cmp = strcmp((*current)->name(), name());
       
   391     if ((group_cmp > 0) || (group_cmp == 0 && name_cmp > 0)) {
       
   392       break;
       
   393     }
       
   394 
       
   395     current = &(*current)->_next;
       
   396   }
       
   397 
       
   398   T* const next = *current;
       
   399   *current = (T*)this;
       
   400   return next;
       
   401 }
       
   402 
       
   403 //
       
   404 // Stat sampler
       
   405 //
       
   406 ZStatSampler::ZStatSampler(const char* group, const char* name, ZStatUnitPrinter printer) :
       
   407     ZStatIterableValue(group, name, sizeof(ZStatSamplerData)),
       
   408     _printer(printer) {}
       
   409 
       
   410 ZStatSamplerData* ZStatSampler::get() const {
       
   411   return get_cpu_local<ZStatSamplerData>(ZCPU::id());
       
   412 }
       
   413 
       
   414 ZStatSamplerData ZStatSampler::collect_and_reset() const {
       
   415   ZStatSamplerData all;
       
   416 
       
   417   const uint32_t ncpus = ZCPU::count();
       
   418   for (uint32_t i = 0; i < ncpus; i++) {
       
   419     ZStatSamplerData* const cpu_data = get_cpu_local<ZStatSamplerData>(i);
       
   420     if (cpu_data->_nsamples > 0) {
       
   421       const uint64_t nsamples = Atomic::xchg((uint64_t)0, &cpu_data->_nsamples);
       
   422       const uint64_t sum = Atomic::xchg((uint64_t)0, &cpu_data->_sum);
       
   423       const uint64_t max = Atomic::xchg((uint64_t)0, &cpu_data->_max);
       
   424       all._nsamples += nsamples;
       
   425       all._sum += sum;
       
   426       if (all._max < max) {
       
   427         all._max = max;
       
   428       }
       
   429     }
       
   430   }
       
   431 
       
   432   return all;
       
   433 }
       
   434 
       
   435 ZStatUnitPrinter ZStatSampler::printer() const {
       
   436   return _printer;
       
   437 }
       
   438 
       
   439 //
       
   440 // Stat counter
       
   441 //
       
   442 ZStatCounter::ZStatCounter(const char* group, const char* name, ZStatUnitPrinter printer) :
       
   443     ZStatIterableValue(group, name, sizeof(ZStatCounterData)),
       
   444     _sampler(group, name, printer) {}
       
   445 
       
   446 ZStatCounterData* ZStatCounter::get() const {
       
   447   return get_cpu_local<ZStatCounterData>(ZCPU::id());
       
   448 }
       
   449 
       
   450 void ZStatCounter::sample_and_reset() const {
       
   451   uint64_t counter = 0;
       
   452 
       
   453   const uint32_t ncpus = ZCPU::count();
       
   454   for (uint32_t i = 0; i < ncpus; i++) {
       
   455     ZStatCounterData* const cpu_data = get_cpu_local<ZStatCounterData>(i);
       
   456     counter += Atomic::xchg((uint64_t)0, &cpu_data->_counter);
       
   457   }
       
   458 
       
   459   ZStatSample(_sampler, counter);
       
   460 }
       
   461 
       
   462 //
       
   463 // Stat unsampled counter
       
   464 //
       
   465 ZStatUnsampledCounter::ZStatUnsampledCounter(const char* name) :
       
   466     ZStatIterableValue("Unsampled", name, sizeof(ZStatCounterData)) {}
       
   467 
       
   468 ZStatCounterData* ZStatUnsampledCounter::get() const {
       
   469   return get_cpu_local<ZStatCounterData>(ZCPU::id());
       
   470 }
       
   471 
       
   472 ZStatCounterData ZStatUnsampledCounter::collect_and_reset() const {
       
   473   ZStatCounterData all;
       
   474 
       
   475   const uint32_t ncpus = ZCPU::count();
       
   476   for (uint32_t i = 0; i < ncpus; i++) {
       
   477     ZStatCounterData* const cpu_data = get_cpu_local<ZStatCounterData>(i);
       
   478     all._counter += Atomic::xchg((uint64_t)0, &cpu_data->_counter);
       
   479   }
       
   480 
       
   481   return all;
       
   482 }
       
   483 
       
   484 //
       
   485 // Stat MMU (Mimimum Mutator Utilization)
       
   486 //
       
   487 ZStatMMUPause::ZStatMMUPause() :
       
   488     _start(0.0),
       
   489     _end(0.0) {}
       
   490 
       
   491 ZStatMMUPause::ZStatMMUPause(const Ticks& start, const Ticks& end) :
       
   492     _start(TimeHelper::counter_to_millis(start.value())),
       
   493     _end(TimeHelper::counter_to_millis(end.value())) {}
       
   494 
       
   495 double ZStatMMUPause::end() const {
       
   496   return _end;
       
   497 }
       
   498 
       
   499 double ZStatMMUPause::overlap(double start, double end) const {
       
   500   const double start_max = MAX2(start, _start);
       
   501   const double end_min = MIN2(end, _end);
       
   502 
       
   503   if (end_min > start_max) {
       
   504     // Overlap found
       
   505     return end_min - start_max;
       
   506   }
       
   507 
       
   508   // No overlap
       
   509   return 0.0;
       
   510 }
       
   511 
       
   512 size_t ZStatMMU::_next = 0;
       
   513 size_t ZStatMMU::_npauses = 0;
       
   514 ZStatMMUPause ZStatMMU::_pauses[200];
       
   515 double ZStatMMU::_mmu_2ms = 100.0;
       
   516 double ZStatMMU::_mmu_5ms = 100.0;
       
   517 double ZStatMMU::_mmu_10ms = 100.0;
       
   518 double ZStatMMU::_mmu_20ms = 100.0;
       
   519 double ZStatMMU::_mmu_50ms = 100.0;
       
   520 double ZStatMMU::_mmu_100ms = 100.0;
       
   521 
       
   522 const ZStatMMUPause& ZStatMMU::pause(size_t index) {
       
   523   return _pauses[(_next - index - 1) % ARRAY_SIZE(_pauses)];
       
   524 }
       
   525 
       
   526 double ZStatMMU::calculate_mmu(double time_slice) {
       
   527   const double end = pause(0).end();
       
   528   const double start = end - time_slice;
       
   529   double time_paused = 0.0;
       
   530 
       
   531   // Find all overlapping pauses
       
   532   for (size_t i = 0; i < _npauses; i++) {
       
   533     const double overlap = pause(i).overlap(start, end);
       
   534     if (overlap == 0.0) {
       
   535       // No overlap
       
   536       break;
       
   537     }
       
   538 
       
   539     time_paused += overlap;
       
   540   }
       
   541 
       
   542   // Calculate MMU
       
   543   const double time_mutator = time_slice - time_paused;
       
   544   return percent_of(time_mutator, time_slice);
       
   545 }
       
   546 
       
   547 void ZStatMMU::register_pause(const Ticks& start, const Ticks& end) {
       
   548   // Add pause
       
   549   const size_t index = _next++ % ARRAY_SIZE(_pauses);
       
   550   _pauses[index] = ZStatMMUPause(start, end);
       
   551   _npauses = MIN2(_npauses + 1, ARRAY_SIZE(_pauses));
       
   552 
       
   553   // Recalculate MMUs
       
   554   _mmu_2ms    = MIN2(_mmu_2ms,   calculate_mmu(2));
       
   555   _mmu_5ms    = MIN2(_mmu_5ms,   calculate_mmu(5));
       
   556   _mmu_10ms   = MIN2(_mmu_10ms,  calculate_mmu(10));
       
   557   _mmu_20ms   = MIN2(_mmu_20ms,  calculate_mmu(20));
       
   558   _mmu_50ms   = MIN2(_mmu_50ms,  calculate_mmu(50));
       
   559   _mmu_100ms  = MIN2(_mmu_100ms, calculate_mmu(100));
       
   560 }
       
   561 
       
   562 void ZStatMMU::print() {
       
   563   log_info(gc, mmu)(
       
   564      "MMU: 2ms/%.1f%%, 5ms/%.1f%%, 10ms/%.1f%%, 20ms/%.1f%%, 50ms/%.1f%%, 100ms/%.1f%%",
       
   565      _mmu_2ms, _mmu_5ms, _mmu_10ms, _mmu_20ms, _mmu_50ms, _mmu_100ms);
       
   566 }
       
   567 
       
   568 //
       
   569 // Stat phases
       
   570 //
       
   571 ConcurrentGCTimer ZStatPhase::_timer;
       
   572 
       
   573 ZStatPhase::ZStatPhase(const char* group, const char* name) :
       
   574     _sampler(group, name, ZStatUnitTime) {}
       
   575 
       
   576 void ZStatPhase::log_start(LogTargetHandle log, bool thread) const {
       
   577   if (!log.is_enabled()) {
       
   578     return;
       
   579   }
       
   580 
       
   581   if (thread) {
       
   582     ResourceMark rm;
       
   583     log.print("%s (%s)", name(), Thread::current()->name());
       
   584   } else {
       
   585     log.print("%s", name());
       
   586   }
       
   587 }
       
   588 
       
   589 void ZStatPhase::log_end(LogTargetHandle log, const Tickspan& duration, bool thread) const {
       
   590   if (!log.is_enabled()) {
       
   591     return;
       
   592   }
       
   593 
       
   594   if (thread) {
       
   595     ResourceMark rm;
       
   596     log.print("%s (%s) %.3fms", name(), Thread::current()->name(), TimeHelper::counter_to_millis(duration.value()));
       
   597   } else {
       
   598     log.print("%s %.3fms", name(), TimeHelper::counter_to_millis(duration.value()));
       
   599   }
       
   600 }
       
   601 
       
   602 ConcurrentGCTimer* ZStatPhase::timer() {
       
   603   return &_timer;
       
   604 }
       
   605 
       
   606 const char* ZStatPhase::name() const {
       
   607   return _sampler.name();
       
   608 }
       
   609 
       
   610 ZStatPhaseCycle::ZStatPhaseCycle(const char* name) :
       
   611     ZStatPhase("Collector", name) {}
       
   612 
       
   613 void ZStatPhaseCycle::register_start(const Ticks& start) const {
       
   614   timer()->register_gc_start(start);
       
   615 
       
   616   ZTracer::tracer()->report_gc_start(ZCollectedHeap::heap()->gc_cause(), start);
       
   617 
       
   618   ZCollectedHeap::heap()->print_heap_before_gc();
       
   619   ZCollectedHeap::heap()->trace_heap_before_gc(ZTracer::tracer());
       
   620 
       
   621   log_info(gc, start)("Garbage Collection (%s)",
       
   622                        GCCause::to_string(ZCollectedHeap::heap()->gc_cause()));
       
   623 }
       
   624 
       
   625 #define ZUSED_FMT                       SIZE_FORMAT "M(%.0lf%%)"
       
   626 #define ZUSED_ARGS(size, max_capacity)  ((size) / M), (percent_of<size_t>(size, max_capacity))
       
   627 
       
   628 void ZStatPhaseCycle::register_end(const Ticks& start, const Ticks& end) const {
       
   629   timer()->register_gc_end(end);
       
   630 
       
   631   ZCollectedHeap::heap()->print_heap_after_gc();
       
   632   ZCollectedHeap::heap()->trace_heap_after_gc(ZTracer::tracer());
       
   633 
       
   634   ZTracer::tracer()->report_gc_end(end, timer()->time_partitions());
       
   635 
       
   636   const Tickspan duration = end - start;
       
   637   ZStatSample(_sampler, duration.value());
       
   638 
       
   639   ZStatLoad::print();
       
   640   ZStatMMU::print();
       
   641   ZStatMark::print();
       
   642   ZStatRelocation::print();
       
   643   ZStatNMethods::print();
       
   644   ZStatReferences::print();
       
   645   ZStatHeap::print();
       
   646 
       
   647   log_info(gc)("Garbage Collection (%s) " ZUSED_FMT "->" ZUSED_FMT,
       
   648                GCCause::to_string(ZCollectedHeap::heap()->gc_cause()),
       
   649                ZUSED_ARGS(ZStatHeap::used_at_mark_start(), ZStatHeap::max_capacity()),
       
   650                ZUSED_ARGS(ZStatHeap::used_at_relocate_end(), ZStatHeap::max_capacity()));
       
   651 }
       
   652 
       
   653 Tickspan ZStatPhasePause::_max;
       
   654 
       
   655 ZStatPhasePause::ZStatPhasePause(const char* name) :
       
   656     ZStatPhase("Phase", name) {}
       
   657 
       
   658 const Tickspan& ZStatPhasePause::max() {
       
   659   return _max;
       
   660 }
       
   661 
       
   662 void ZStatPhasePause::register_start(const Ticks& start) const {
       
   663   timer()->register_gc_pause_start(name(), start);
       
   664 
       
   665   LogTarget(Debug, gc, phases, start) log;
       
   666   log_start(log);
       
   667 }
       
   668 
       
   669 void ZStatPhasePause::register_end(const Ticks& start, const Ticks& end) const {
       
   670   timer()->register_gc_pause_end(end);
       
   671 
       
   672   const Tickspan duration = end - start;
       
   673   ZStatSample(_sampler, duration.value());
       
   674 
       
   675   // Track max pause time
       
   676   if (_max < duration) {
       
   677     _max = duration;
       
   678   }
       
   679 
       
   680   // Track minimum mutator utilization
       
   681   ZStatMMU::register_pause(start, end);
       
   682 
       
   683   LogTarget(Info, gc, phases) log;
       
   684   log_end(log, duration);
       
   685 }
       
   686 
       
   687 ZStatPhaseConcurrent::ZStatPhaseConcurrent(const char* name) :
       
   688     ZStatPhase("Phase", name) {}
       
   689 
       
   690 void ZStatPhaseConcurrent::register_start(const Ticks& start) const {
       
   691   timer()->register_gc_concurrent_start(name(), start);
       
   692 
       
   693   LogTarget(Debug, gc, phases, start) log;
       
   694   log_start(log);
       
   695 }
       
   696 
       
   697 void ZStatPhaseConcurrent::register_end(const Ticks& start, const Ticks& end) const {
       
   698   timer()->register_gc_concurrent_end(end);
       
   699 
       
   700   const Tickspan duration = end - start;
       
   701   ZStatSample(_sampler, duration.value());
       
   702 
       
   703   LogTarget(Info, gc, phases) log;
       
   704   log_end(log, duration);
       
   705 }
       
   706 
       
   707 ZStatSubPhase::ZStatSubPhase(const char* name) :
       
   708     ZStatPhase("Subphase", name) {}
       
   709 
       
   710 void ZStatSubPhase::register_start(const Ticks& start) const {
       
   711   LogTarget(Debug, gc, phases, start) log;
       
   712   log_start(log, true /* thread */);
       
   713 }
       
   714 
       
   715 void ZStatSubPhase::register_end(const Ticks& start, const Ticks& end) const {
       
   716   ZTracer::tracer()->report_thread_phase(*this, start, end);
       
   717 
       
   718   const Tickspan duration = end - start;
       
   719   ZStatSample(_sampler, duration.value());
       
   720 
       
   721   LogTarget(Debug, gc, phases) log;
       
   722   log_end(log, duration, true /* thread */);
       
   723 }
       
   724 
       
   725 ZStatCriticalPhase::ZStatCriticalPhase(const char* name, bool verbose) :
       
   726     ZStatPhase("Critical", name),
       
   727     _counter("Critical", name, ZStatUnitOpsPerSecond),
       
   728     _verbose(verbose) {}
       
   729 
       
   730 void ZStatCriticalPhase::register_start(const Ticks& start) const {
       
   731   LogTarget(Debug, gc, start) log;
       
   732   log_start(log, true /* thread */);
       
   733 }
       
   734 
       
   735 void ZStatCriticalPhase::register_end(const Ticks& start, const Ticks& end) const {
       
   736   ZTracer::tracer()->report_thread_phase(*this, start, end);
       
   737 
       
   738   const Tickspan duration = end - start;
       
   739   ZStatSample(_sampler, duration.value());
       
   740   ZStatInc(_counter);
       
   741 
       
   742   if (_verbose) {
       
   743     LogTarget(Info, gc) log;
       
   744     log_end(log, duration, true /* thread */);
       
   745   } else {
       
   746     LogTarget(Debug, gc) log;
       
   747     log_end(log, duration, true /* thread */);
       
   748   }
       
   749 }
       
   750 
       
   751 //
       
   752 // Stat sample/inc
       
   753 //
       
   754 void ZStatSample(const ZStatSampler& sampler, uint64_t value, bool trace) {
       
   755   ZStatSamplerData* const cpu_data = sampler.get();
       
   756   Atomic::add(1u, &cpu_data->_nsamples);
       
   757   Atomic::add(value, &cpu_data->_sum);
       
   758 
       
   759   uint64_t max = cpu_data->_max;
       
   760   for (;;) {
       
   761     if (max >= value) {
       
   762       // Not max
       
   763       break;
       
   764     }
       
   765 
       
   766     const uint64_t new_max = value;
       
   767     const uint64_t prev_max = Atomic::cmpxchg(new_max, &cpu_data->_max, max);
       
   768     if (prev_max == max) {
       
   769       // Success
       
   770       break;
       
   771     }
       
   772 
       
   773     // Retry
       
   774     max = prev_max;
       
   775   }
       
   776 
       
   777   if (trace) {
       
   778     ZTracer::tracer()->report_stat_sampler(sampler, value);
       
   779   }
       
   780 }
       
   781 
       
   782 void ZStatInc(const ZStatCounter& counter, uint64_t increment, bool trace) {
       
   783   ZStatCounterData* const cpu_data = counter.get();
       
   784   const uint64_t value = Atomic::add(increment, &cpu_data->_counter);
       
   785 
       
   786   if (trace) {
       
   787     ZTracer::tracer()->report_stat_counter(counter, increment, value);
       
   788   }
       
   789 }
       
   790 
       
   791 void ZStatInc(const ZStatUnsampledCounter& counter, uint64_t increment) {
       
   792   ZStatCounterData* const cpu_data = counter.get();
       
   793   Atomic::add(increment, &cpu_data->_counter);
       
   794 }
       
   795 
       
   796 //
       
   797 // Stat allocation rate
       
   798 //
       
   799 const ZStatUnsampledCounter ZStatAllocRate::_counter("Allocation Rate");
       
   800 TruncatedSeq                ZStatAllocRate::_rate(ZStatAllocRate::sample_window_sec * ZStatAllocRate::sample_hz);
       
   801 TruncatedSeq                ZStatAllocRate::_rate_avg(ZStatAllocRate::sample_window_sec * ZStatAllocRate::sample_hz);
       
   802 
       
   803 const ZStatUnsampledCounter& ZStatAllocRate::counter() {
       
   804   return _counter;
       
   805 }
       
   806 
       
   807 uint64_t ZStatAllocRate::sample_and_reset() {
       
   808   const ZStatCounterData bytes_per_sample = _counter.collect_and_reset();
       
   809   const uint64_t bytes_per_second = bytes_per_sample._counter * sample_hz;
       
   810 
       
   811   _rate.add(bytes_per_second);
       
   812   _rate_avg.add(_rate.avg());
       
   813 
       
   814   return bytes_per_second;
       
   815 }
       
   816 
       
   817 double ZStatAllocRate::avg() {
       
   818   return _rate.avg();
       
   819 }
       
   820 
       
   821 double ZStatAllocRate::avg_sd() {
       
   822   return _rate_avg.sd();
       
   823 }
       
   824 
       
   825 //
       
   826 // Stat thread
       
   827 //
       
   828 ZStat::ZStat() :
       
   829     _metronome(sample_hz) {
       
   830   set_name("ZStat");
       
   831   create_and_start();
       
   832 }
       
   833 
       
   834 void ZStat::sample_and_collect(ZStatSamplerHistory* history) const {
       
   835   // Sample counters
       
   836   for (const ZStatCounter* counter = ZStatCounter::first(); counter != NULL; counter = counter->next()) {
       
   837     counter->sample_and_reset();
       
   838   }
       
   839 
       
   840   // Collect samples
       
   841   for (const ZStatSampler* sampler = ZStatSampler::first(); sampler != NULL; sampler = sampler->next()) {
       
   842     ZStatSamplerHistory& sampler_history = history[sampler->id()];
       
   843     sampler_history.add(sampler->collect_and_reset());
       
   844   }
       
   845 }
       
   846 
       
   847 bool ZStat::should_print(LogTargetHandle log) const {
       
   848   return log.is_enabled() && (_metronome.nticks() % ZStatisticsInterval == 0);
       
   849 }
       
   850 
       
   851 void ZStat::print(LogTargetHandle log, const ZStatSamplerHistory* history) const {
       
   852   // Print
       
   853   log.print("=== Garbage Collection Statistics =======================================================================================================================");
       
   854   log.print("                                                             Last 10s              Last 10m              Last 10h                Total");
       
   855   log.print("                                                             Avg / Max             Avg / Max             Avg / Max             Avg / Max");
       
   856 
       
   857   for (const ZStatSampler* sampler = ZStatSampler::first(); sampler != NULL; sampler = sampler->next()) {
       
   858     const ZStatSamplerHistory& sampler_history = history[sampler->id()];
       
   859     const ZStatUnitPrinter printer = sampler->printer();
       
   860     printer(log, *sampler, sampler_history);
       
   861   }
       
   862 
       
   863   log.print("=========================================================================================================================================================");
       
   864 }
       
   865 
       
   866 void ZStat::run_service() {
       
   867   ZStatSamplerHistory* const history = new ZStatSamplerHistory[ZStatSampler::count()];
       
   868   LogTarget(Info, gc, stats) log;
       
   869 
       
   870   // Main loop
       
   871   while (_metronome.wait_for_tick()) {
       
   872     sample_and_collect(history);
       
   873     if (should_print(log)) {
       
   874       print(log, history);
       
   875     }
       
   876   }
       
   877 
       
   878   delete [] history;
       
   879 }
       
   880 
       
   881 void ZStat::stop_service() {
       
   882   _metronome.stop();
       
   883 }
       
   884 
       
   885 //
       
   886 // Stat table
       
   887 //
       
   888 class ZStatTablePrinter {
       
   889 private:
       
   890   static const size_t _buffer_size = 256;
       
   891 
       
   892   const size_t _column0_width;
       
   893   const size_t _columnN_width;
       
   894   char         _buffer[_buffer_size];
       
   895 
       
   896 public:
       
   897   class ZColumn {
       
   898   private:
       
   899     char* const  _buffer;
       
   900     const size_t _position;
       
   901     const size_t _width;
       
   902     const size_t _width_next;
       
   903 
       
   904     ZColumn next() const {
       
   905       // Insert space between columns
       
   906       _buffer[_position + _width] = ' ';
       
   907       return ZColumn(_buffer, _position + _width + 1, _width_next, _width_next);
       
   908     }
       
   909 
       
   910     size_t print(size_t position, const char* fmt, va_list va) {
       
   911       const int res = jio_vsnprintf(_buffer + position, _buffer_size - position, fmt, va);
       
   912       if (res < 0) {
       
   913         return 0;
       
   914       }
       
   915 
       
   916       return (size_t)res;
       
   917     }
       
   918 
       
   919   public:
       
   920     ZColumn(char* buffer, size_t position, size_t width, size_t width_next) :
       
   921         _buffer(buffer),
       
   922         _position(position),
       
   923         _width(width),
       
   924         _width_next(width_next) {}
       
   925 
       
   926     ZColumn left(const char* fmt, ...) ATTRIBUTE_PRINTF(2, 3) {
       
   927       va_list va;
       
   928 
       
   929       va_start(va, fmt);
       
   930       const size_t written = print(_position, fmt, va);
       
   931       va_end(va);
       
   932 
       
   933       if (written < _width) {
       
   934         // Fill empty space
       
   935         memset(_buffer + _position + written, ' ', _width - written);
       
   936       }
       
   937 
       
   938       return next();
       
   939     }
       
   940 
       
   941     ZColumn right(const char* fmt, ...) ATTRIBUTE_PRINTF(2, 3) {
       
   942       va_list va;
       
   943 
       
   944       va_start(va, fmt);
       
   945       const size_t written = print(_position, fmt, va);
       
   946       va_end(va);
       
   947 
       
   948       if (written > _width) {
       
   949         // Line too long
       
   950         return fill('?');
       
   951       }
       
   952 
       
   953       if (written < _width) {
       
   954         // Short line, move all to right
       
   955         memmove(_buffer + _position + _width - written, _buffer + _position, written);
       
   956 
       
   957         // Fill empty space
       
   958         memset(_buffer + _position, ' ', _width - written);
       
   959       }
       
   960 
       
   961       return next();
       
   962     }
       
   963 
       
   964     ZColumn center(const char* fmt, ...) ATTRIBUTE_PRINTF(2, 3) {
       
   965       va_list va;
       
   966 
       
   967       va_start(va, fmt);
       
   968       const size_t written = print(_position, fmt, va);
       
   969       va_end(va);
       
   970 
       
   971       if (written > _width) {
       
   972         // Line too long
       
   973         return fill('?');
       
   974       }
       
   975 
       
   976       if (written < _width) {
       
   977         // Short line, move all to center
       
   978         const size_t start_space = (_width - written) / 2;
       
   979         const size_t end_space = _width - written - start_space;
       
   980         memmove(_buffer + _position + start_space, _buffer + _position, written);
       
   981 
       
   982         // Fill empty spaces
       
   983         memset(_buffer + _position, ' ', start_space);
       
   984         memset(_buffer + _position + start_space + written, ' ', end_space);
       
   985       }
       
   986 
       
   987       return next();
       
   988     }
       
   989 
       
   990     ZColumn fill(char filler = ' ') {
       
   991       memset(_buffer + _position, filler, _width);
       
   992       return next();
       
   993     }
       
   994 
       
   995     const char* end() {
       
   996       _buffer[_position] = '\0';
       
   997       return _buffer;
       
   998     }
       
   999   };
       
  1000 
       
  1001 public:
       
  1002   ZStatTablePrinter(size_t column0_width, size_t columnN_width) :
       
  1003       _column0_width(column0_width),
       
  1004       _columnN_width(columnN_width) {}
       
  1005 
       
  1006   ZColumn operator()() {
       
  1007     return ZColumn(_buffer, 0, _column0_width, _columnN_width);
       
  1008   }
       
  1009 };
       
  1010 
       
  1011 //
       
  1012 // Stat cycle
       
  1013 //
       
  1014 uint64_t  ZStatCycle::_ncycles = 0;
       
  1015 Ticks     ZStatCycle::_start_of_last;
       
  1016 Ticks     ZStatCycle::_end_of_last;
       
  1017 NumberSeq ZStatCycle::_normalized_duration(0.3 /* alpha */);
       
  1018 
       
  1019 void ZStatCycle::at_start() {
       
  1020   _start_of_last = Ticks::now();
       
  1021 }
       
  1022 
       
  1023 void ZStatCycle::at_end(double boost_factor) {
       
  1024   _end_of_last = Ticks::now();
       
  1025   _ncycles++;
       
  1026 
       
  1027   // Calculate normalized cycle duration. The measured duration is
       
  1028   // normalized using the boost factor to avoid artificial deflation
       
  1029   // of the duration when boost mode is enabled.
       
  1030   const double duration = (_end_of_last - _start_of_last).seconds();
       
  1031   const double normalized_duration = duration * boost_factor;
       
  1032   _normalized_duration.add(normalized_duration);
       
  1033 }
       
  1034 
       
  1035 uint64_t ZStatCycle::ncycles() {
       
  1036   return _ncycles;
       
  1037 }
       
  1038 
       
  1039 const AbsSeq& ZStatCycle::normalized_duration() {
       
  1040   return _normalized_duration;
       
  1041 }
       
  1042 
       
  1043 double ZStatCycle::time_since_last() {
       
  1044   if (_ncycles == 0) {
       
  1045     // Return time since VM start-up
       
  1046     return os::elapsedTime();
       
  1047   }
       
  1048 
       
  1049   const Ticks now = Ticks::now();
       
  1050   const Tickspan time_since_last = now - _end_of_last;
       
  1051   return time_since_last.seconds();
       
  1052 }
       
  1053 
       
  1054 //
       
  1055 // Stat load
       
  1056 //
       
  1057 void ZStatLoad::print() {
       
  1058   double loadavg[3] = {};
       
  1059   os::loadavg(loadavg, ARRAY_SIZE(loadavg));
       
  1060   log_info(gc, load)("Load: %.2f/%.2f/%.2f", loadavg[0], loadavg[1], loadavg[2]);
       
  1061 }
       
  1062 
       
  1063 //
       
  1064 // Stat mark
       
  1065 //
       
  1066 size_t ZStatMark::_nstripes;
       
  1067 size_t ZStatMark::_nproactiveflush;
       
  1068 size_t ZStatMark::_nterminateflush;
       
  1069 size_t ZStatMark::_ntrycomplete;
       
  1070 size_t ZStatMark::_ncontinue;
       
  1071 
       
  1072 void ZStatMark::set_at_mark_start(size_t nstripes) {
       
  1073   _nstripes = nstripes;
       
  1074 }
       
  1075 
       
  1076 void ZStatMark::set_at_mark_end(size_t nproactiveflush,
       
  1077                                 size_t nterminateflush,
       
  1078                                 size_t ntrycomplete,
       
  1079                                 size_t ncontinue) {
       
  1080   _nproactiveflush = nproactiveflush;
       
  1081   _nterminateflush = nterminateflush;
       
  1082   _ntrycomplete = ntrycomplete;
       
  1083   _ncontinue = ncontinue;
       
  1084 }
       
  1085 
       
  1086 void ZStatMark::print() {
       
  1087   log_info(gc, marking)("Mark: "
       
  1088                         SIZE_FORMAT " stripe(s), "
       
  1089                         SIZE_FORMAT " proactive flush(es), "
       
  1090                         SIZE_FORMAT " terminate flush(es), "
       
  1091                         SIZE_FORMAT " completion(s), "
       
  1092                         SIZE_FORMAT " continuation(s) ",
       
  1093                         _nstripes,
       
  1094                         _nproactiveflush,
       
  1095                         _nterminateflush,
       
  1096                         _ntrycomplete,
       
  1097                         _ncontinue);
       
  1098 }
       
  1099 
       
  1100 //
       
  1101 // Stat relocation
       
  1102 //
       
  1103 size_t ZStatRelocation::_relocating;
       
  1104 bool ZStatRelocation::_success;
       
  1105 
       
  1106 void ZStatRelocation::set_at_select_relocation_set(size_t relocating) {
       
  1107   _relocating = relocating;
       
  1108 }
       
  1109 
       
  1110 void ZStatRelocation::set_at_relocate_end(bool success) {
       
  1111   _success = success;
       
  1112 }
       
  1113 
       
  1114 void ZStatRelocation::print() {
       
  1115   if (_success) {
       
  1116     log_info(gc, reloc)("Relocation: Successful, " SIZE_FORMAT "M relocated", _relocating / M);
       
  1117   } else {
       
  1118     log_info(gc, reloc)("Relocation: Incomplete");
       
  1119   }
       
  1120 }
       
  1121 
       
  1122 //
       
  1123 // Stat nmethods
       
  1124 //
       
  1125 void ZStatNMethods::print() {
       
  1126   log_info(gc, nmethod)("NMethods: " SIZE_FORMAT " registered, " SIZE_FORMAT " unregistered",
       
  1127                         ZNMethodTable::registered_nmethods(),
       
  1128                         ZNMethodTable::unregistered_nmethods());
       
  1129 }
       
  1130 
       
  1131 //
       
  1132 // Stat references
       
  1133 //
       
  1134 ZStatReferences::ZCount ZStatReferences::_soft;
       
  1135 ZStatReferences::ZCount ZStatReferences::_weak;
       
  1136 ZStatReferences::ZCount ZStatReferences::_final;
       
  1137 ZStatReferences::ZCount ZStatReferences::_phantom;
       
  1138 
       
  1139 void ZStatReferences::set(ZCount* count, size_t encountered, size_t discovered, size_t enqueued) {
       
  1140   count->encountered = encountered;
       
  1141   count->discovered = discovered;
       
  1142   count->enqueued = enqueued;
       
  1143 }
       
  1144 
       
  1145 void ZStatReferences::set_soft(size_t encountered, size_t discovered, size_t enqueued) {
       
  1146   set(&_soft, encountered, discovered, enqueued);
       
  1147 }
       
  1148 
       
  1149 void ZStatReferences::set_weak(size_t encountered, size_t discovered, size_t enqueued) {
       
  1150   set(&_weak, encountered, discovered, enqueued);
       
  1151 }
       
  1152 
       
  1153 void ZStatReferences::set_final(size_t encountered, size_t discovered, size_t enqueued) {
       
  1154   set(&_final, encountered, discovered, enqueued);
       
  1155 }
       
  1156 
       
  1157 void ZStatReferences::set_phantom(size_t encountered, size_t discovered, size_t enqueued) {
       
  1158   set(&_phantom, encountered, discovered, enqueued);
       
  1159 }
       
  1160 
       
  1161 void ZStatReferences::print(const char* name, const ZStatReferences::ZCount& ref) {
       
  1162   log_info(gc, ref)("%s: "
       
  1163                     SIZE_FORMAT " encountered, "
       
  1164                     SIZE_FORMAT " discovered, "
       
  1165                     SIZE_FORMAT " enqueued",
       
  1166                     name,
       
  1167                     ref.encountered,
       
  1168                     ref.discovered,
       
  1169                     ref.enqueued);
       
  1170 }
       
  1171 
       
  1172 void ZStatReferences::print() {
       
  1173   print("Soft", _soft);
       
  1174   print("Weak", _weak);
       
  1175   print("Final", _final);
       
  1176   print("Phantom", _phantom);
       
  1177 }
       
  1178 
       
  1179 //
       
  1180 // Stat heap
       
  1181 //
       
  1182 ZStatHeap::ZAtInitialize ZStatHeap::_at_initialize;
       
  1183 ZStatHeap::ZAtMarkStart ZStatHeap::_at_mark_start;
       
  1184 ZStatHeap::ZAtMarkEnd ZStatHeap::_at_mark_end;
       
  1185 ZStatHeap::ZAtRelocateStart ZStatHeap::_at_relocate_start;
       
  1186 ZStatHeap::ZAtRelocateEnd ZStatHeap::_at_relocate_end;
       
  1187 
       
  1188 #define ZSIZE_NA               "%9s", "-"
       
  1189 #define ZSIZE_ARGS(size)       SIZE_FORMAT_W(8) "M (%.0lf%%)", \
       
  1190                                ((size) / M), (percent_of<size_t>(size, _at_initialize.max_capacity))
       
  1191 
       
  1192 size_t ZStatHeap::available(size_t used) {
       
  1193   return _at_initialize.max_capacity - used;
       
  1194 }
       
  1195 
       
  1196 size_t ZStatHeap::reserve(size_t used) {
       
  1197   return MIN2(_at_initialize.max_reserve, available(used));
       
  1198 }
       
  1199 
       
  1200 size_t ZStatHeap::free(size_t used) {
       
  1201   return available(used) - reserve(used);
       
  1202 }
       
  1203 
       
  1204 void ZStatHeap::set_at_initialize(size_t max_capacity,
       
  1205                                   size_t max_reserve) {
       
  1206   _at_initialize.max_capacity = max_capacity;
       
  1207   _at_initialize.max_reserve = max_reserve;
       
  1208 }
       
  1209 
       
  1210 void ZStatHeap::set_at_mark_start(size_t capacity,
       
  1211                                   size_t used) {
       
  1212   _at_mark_start.capacity = capacity;
       
  1213   _at_mark_start.reserve = reserve(used);
       
  1214   _at_mark_start.used = used;
       
  1215   _at_mark_start.free = free(used);
       
  1216 }
       
  1217 
       
  1218 void ZStatHeap::set_at_mark_end(size_t capacity,
       
  1219                                 size_t allocated,
       
  1220                                 size_t used) {
       
  1221   _at_mark_end.capacity = capacity;
       
  1222   _at_mark_end.reserve = reserve(used);
       
  1223   _at_mark_end.allocated = allocated;
       
  1224   _at_mark_end.used = used;
       
  1225   _at_mark_end.free = free(used);
       
  1226 }
       
  1227 
       
  1228 void ZStatHeap::set_at_select_relocation_set(size_t live,
       
  1229                                              size_t garbage,
       
  1230                                              size_t reclaimed) {
       
  1231   _at_mark_end.live = live;
       
  1232   _at_mark_end.garbage = garbage;
       
  1233 
       
  1234   _at_relocate_start.garbage = garbage - reclaimed;
       
  1235   _at_relocate_start.reclaimed = reclaimed;
       
  1236 }
       
  1237 
       
  1238 void ZStatHeap::set_at_relocate_start(size_t capacity,
       
  1239                                       size_t allocated,
       
  1240                                       size_t used) {
       
  1241   _at_relocate_start.capacity = capacity;
       
  1242   _at_relocate_start.reserve = reserve(used);
       
  1243   _at_relocate_start.allocated = allocated;
       
  1244   _at_relocate_start.used = used;
       
  1245   _at_relocate_start.free = free(used);
       
  1246 }
       
  1247 
       
  1248 void ZStatHeap::set_at_relocate_end(size_t capacity,
       
  1249                                     size_t allocated,
       
  1250                                     size_t reclaimed,
       
  1251                                     size_t used,
       
  1252                                     size_t used_high,
       
  1253                                     size_t used_low) {
       
  1254   _at_relocate_end.capacity = capacity;
       
  1255   _at_relocate_end.capacity_high = capacity;
       
  1256   _at_relocate_end.capacity_low = _at_mark_start.capacity;
       
  1257   _at_relocate_end.reserve = reserve(used);
       
  1258   _at_relocate_end.reserve_high = reserve(used_low);
       
  1259   _at_relocate_end.reserve_low = reserve(used_high);
       
  1260   _at_relocate_end.garbage = _at_mark_end.garbage - reclaimed;
       
  1261   _at_relocate_end.allocated = allocated;
       
  1262   _at_relocate_end.reclaimed = reclaimed;
       
  1263   _at_relocate_end.used = used;
       
  1264   _at_relocate_end.used_high = used_high;
       
  1265   _at_relocate_end.used_low = used_low;
       
  1266   _at_relocate_end.free = free(used);
       
  1267   _at_relocate_end.free_high = free(used_low);
       
  1268   _at_relocate_end.free_low = free(used_high);
       
  1269 }
       
  1270 
       
  1271 size_t ZStatHeap::max_capacity() {
       
  1272   return _at_initialize.max_capacity;
       
  1273 }
       
  1274 
       
  1275 size_t ZStatHeap::used_at_mark_start() {
       
  1276   return _at_mark_start.used;
       
  1277 }
       
  1278 
       
  1279 size_t ZStatHeap::used_at_relocate_end() {
       
  1280   return _at_relocate_end.used;
       
  1281 }
       
  1282 
       
  1283 void ZStatHeap::print() {
       
  1284   ZStatTablePrinter table(10, 18);
       
  1285   log_info(gc, heap)("%s", table()
       
  1286                      .fill()
       
  1287                      .center("Mark Start")
       
  1288                      .center("Mark End")
       
  1289                      .center("Relocate Start")
       
  1290                      .center("Relocate End")
       
  1291                      .center("High")
       
  1292                      .center("Low")
       
  1293                      .end());
       
  1294   log_info(gc, heap)("%s", table()
       
  1295                      .right("Capacity:")
       
  1296                      .left(ZSIZE_ARGS(_at_mark_start.capacity))
       
  1297                      .left(ZSIZE_ARGS(_at_mark_end.capacity))
       
  1298                      .left(ZSIZE_ARGS(_at_relocate_start.capacity))
       
  1299                      .left(ZSIZE_ARGS(_at_relocate_end.capacity))
       
  1300                      .left(ZSIZE_ARGS(_at_relocate_end.capacity_high))
       
  1301                      .left(ZSIZE_ARGS(_at_relocate_end.capacity_low))
       
  1302                      .end());
       
  1303   log_info(gc, heap)("%s", table()
       
  1304                      .right("Reserve:")
       
  1305                      .left(ZSIZE_ARGS(_at_mark_start.reserve))
       
  1306                      .left(ZSIZE_ARGS(_at_mark_end.reserve))
       
  1307                      .left(ZSIZE_ARGS(_at_relocate_start.reserve))
       
  1308                      .left(ZSIZE_ARGS(_at_relocate_end.reserve))
       
  1309                      .left(ZSIZE_ARGS(_at_relocate_end.reserve_high))
       
  1310                      .left(ZSIZE_ARGS(_at_relocate_end.reserve_low))
       
  1311                      .end());
       
  1312   log_info(gc, heap)("%s", table()
       
  1313                      .right("Free:")
       
  1314                      .left(ZSIZE_ARGS(_at_mark_start.free))
       
  1315                      .left(ZSIZE_ARGS(_at_mark_end.free))
       
  1316                      .left(ZSIZE_ARGS(_at_relocate_start.free))
       
  1317                      .left(ZSIZE_ARGS(_at_relocate_end.free))
       
  1318                      .left(ZSIZE_ARGS(_at_relocate_end.free_high))
       
  1319                      .left(ZSIZE_ARGS(_at_relocate_end.free_low))
       
  1320                      .end());
       
  1321   log_info(gc, heap)("%s", table()
       
  1322                      .right("Used:")
       
  1323                      .left(ZSIZE_ARGS(_at_mark_start.used))
       
  1324                      .left(ZSIZE_ARGS(_at_mark_end.used))
       
  1325                      .left(ZSIZE_ARGS(_at_relocate_start.used))
       
  1326                      .left(ZSIZE_ARGS(_at_relocate_end.used))
       
  1327                      .left(ZSIZE_ARGS(_at_relocate_end.used_high))
       
  1328                      .left(ZSIZE_ARGS(_at_relocate_end.used_low))
       
  1329                      .end());
       
  1330   log_info(gc, heap)("%s", table()
       
  1331                      .right("Live:")
       
  1332                      .left(ZSIZE_NA)
       
  1333                      .left(ZSIZE_ARGS(_at_mark_end.live))
       
  1334                      .left(ZSIZE_ARGS(_at_mark_end.live /* Same as at mark end */))
       
  1335                      .left(ZSIZE_ARGS(_at_mark_end.live /* Same as at mark end */))
       
  1336                      .left(ZSIZE_NA)
       
  1337                      .left(ZSIZE_NA)
       
  1338                      .end());
       
  1339   log_info(gc, heap)("%s", table()
       
  1340                      .right("Allocated:")
       
  1341                      .left(ZSIZE_NA)
       
  1342                      .left(ZSIZE_ARGS(_at_mark_end.allocated))
       
  1343                      .left(ZSIZE_ARGS(_at_relocate_start.allocated))
       
  1344                      .left(ZSIZE_ARGS(_at_relocate_end.allocated))
       
  1345                      .left(ZSIZE_NA)
       
  1346                      .left(ZSIZE_NA)
       
  1347                      .end());
       
  1348   log_info(gc, heap)("%s", table()
       
  1349                      .right("Garbage:")
       
  1350                      .left(ZSIZE_NA)
       
  1351                      .left(ZSIZE_ARGS(_at_mark_end.garbage))
       
  1352                      .left(ZSIZE_ARGS(_at_relocate_start.garbage))
       
  1353                      .left(ZSIZE_ARGS(_at_relocate_end.garbage))
       
  1354                      .left(ZSIZE_NA)
       
  1355                      .left(ZSIZE_NA)
       
  1356                      .end());
       
  1357   log_info(gc, heap)("%s", table()
       
  1358                      .right("Reclaimed:")
       
  1359                      .left(ZSIZE_NA)
       
  1360                      .left(ZSIZE_NA)
       
  1361                      .left(ZSIZE_ARGS(_at_relocate_start.reclaimed))
       
  1362                      .left(ZSIZE_ARGS(_at_relocate_end.reclaimed))
       
  1363                      .left(ZSIZE_NA)
       
  1364                      .left(ZSIZE_NA)
       
  1365                      .end());
       
  1366 }