1 /*
   2  * Copyright (c) 2015, 2019, 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 #ifndef SHARE_GC_Z_ZSTAT_HPP
  25 #define SHARE_GC_Z_ZSTAT_HPP
  26 
  27 #include "gc/shared/concurrentGCThread.hpp"
  28 #include "gc/shared/gcCause.hpp"
  29 #include "gc/shared/gcTimer.hpp"
  30 #include "gc/z/zMetronome.hpp"
  31 #include "logging/logHandle.hpp"
  32 #include "memory/allocation.hpp"
  33 #include "utilities/globalDefinitions.hpp"
  34 #include "utilities/numberSeq.hpp"
  35 #include "utilities/ticks.hpp"
  36 
  37 class ZPage;
  38 class ZRelocationSetSelectorGroupStats;
  39 class ZStatSampler;
  40 class ZStatSamplerHistory;
  41 struct ZStatCounterData;
  42 struct ZStatSamplerData;
  43 
  44 //
  45 // Stat unit printers
  46 //
  47 typedef void (*ZStatUnitPrinter)(LogTargetHandle log, const ZStatSampler&, const ZStatSamplerHistory&);
  48 
  49 void ZStatUnitTime(LogTargetHandle log, const ZStatSampler& sampler, const ZStatSamplerHistory& history);
  50 void ZStatUnitBytes(LogTargetHandle log, const ZStatSampler& sampler, const ZStatSamplerHistory& history);
  51 void ZStatUnitThreads(LogTargetHandle log, const ZStatSampler& sampler, const ZStatSamplerHistory& history);
  52 void ZStatUnitBytesPerSecond(LogTargetHandle log, const ZStatSampler& sampler, const ZStatSamplerHistory& history);
  53 void ZStatUnitOpsPerSecond(LogTargetHandle log, const ZStatSampler& sampler, const ZStatSamplerHistory& history);
  54 
  55 //
  56 // Stat value
  57 //
  58 class ZStatValue {
  59 private:
  60   static uintptr_t _base;
  61   static uint32_t  _cpu_offset;
  62 
  63   const char* const _group;
  64   const char* const _name;
  65   const uint32_t    _id;
  66   const uint32_t    _offset;
  67 
  68 protected:
  69   ZStatValue(const char* group,
  70              const char* name,
  71              uint32_t id,
  72              uint32_t size);
  73 
  74   template <typename T> T* get_cpu_local(uint32_t cpu) const;
  75 
  76 public:
  77   static void initialize();
  78 
  79   const char* group() const;
  80   const char* name() const;
  81   uint32_t id() const;
  82 };
  83 
  84 //
  85 // Stat iterable value
  86 //
  87 template <typename T>
  88 class ZStatIterableValue : public ZStatValue {
  89 private:
  90   static uint32_t _count;
  91   static T*       _first;
  92 
  93   T* _next;
  94 
  95   T* insert() const;
  96 
  97 protected:
  98   ZStatIterableValue(const char* group,
  99                      const char* name,
 100                      uint32_t size);
 101 
 102 public:
 103   static uint32_t count() {
 104     return _count;
 105   }
 106 
 107   static T* first() {
 108     return _first;
 109   }
 110 
 111   T* next() const {
 112     return _next;
 113   }
 114 };
 115 
 116 //
 117 // Stat sampler
 118 //
 119 class ZStatSampler : public ZStatIterableValue<ZStatSampler> {
 120 private:
 121   const ZStatUnitPrinter _printer;
 122 
 123 public:
 124   ZStatSampler(const char* group,
 125                const char* name,
 126                ZStatUnitPrinter printer);
 127 
 128   ZStatSamplerData* get() const;
 129   ZStatSamplerData collect_and_reset() const;
 130 
 131   ZStatUnitPrinter printer() const;
 132 };
 133 
 134 //
 135 // Stat counter
 136 //
 137 class ZStatCounter : public ZStatIterableValue<ZStatCounter> {
 138 private:
 139   const ZStatSampler _sampler;
 140 
 141 public:
 142   ZStatCounter(const char* group,
 143                const char* name,
 144                ZStatUnitPrinter printer);
 145 
 146   ZStatCounterData* get() const;
 147   void sample_and_reset() const;
 148 };
 149 
 150 //
 151 // Stat unsampled counter
 152 //
 153 class ZStatUnsampledCounter : public ZStatIterableValue<ZStatUnsampledCounter> {
 154 public:
 155   ZStatUnsampledCounter(const char* name);
 156 
 157   ZStatCounterData* get() const;
 158   ZStatCounterData collect_and_reset() const;
 159 };
 160 
 161 //
 162 // Stat MMU (Minimum Mutator Utilization)
 163 //
 164 class ZStatMMUPause {
 165 private:
 166   double _start;
 167   double _end;
 168 
 169 public:
 170   ZStatMMUPause();
 171   ZStatMMUPause(const Ticks& start, const Ticks& end);
 172 
 173   double end() const;
 174   double overlap(double start, double end) const;
 175 };
 176 
 177 class ZStatMMU {
 178 private:
 179   static size_t        _next;
 180   static size_t        _npauses;
 181   static ZStatMMUPause _pauses[200]; // Record the last 200 pauses
 182 
 183   static double _mmu_2ms;
 184   static double _mmu_5ms;
 185   static double _mmu_10ms;
 186   static double _mmu_20ms;
 187   static double _mmu_50ms;
 188   static double _mmu_100ms;
 189 
 190   static const ZStatMMUPause& pause(size_t index);
 191   static double calculate_mmu(double time_slice);
 192 
 193 public:
 194   static void register_pause(const Ticks& start, const Ticks& end);
 195 
 196   static void print();
 197 };
 198 
 199 //
 200 // Stat phases
 201 //
 202 class ZStatPhase {
 203 private:
 204   static ConcurrentGCTimer _timer;
 205 
 206 protected:
 207   const ZStatSampler _sampler;
 208 
 209   ZStatPhase(const char* group, const char* name);
 210 
 211   void log_start(LogTargetHandle log, bool thread = false) const;
 212   void log_end(LogTargetHandle log, const Tickspan& duration, bool thread = false) const;
 213 
 214 public:
 215   static ConcurrentGCTimer* timer();
 216 
 217   const char* name() const;
 218 
 219   virtual void register_start(const Ticks& start) const = 0;
 220   virtual void register_end(const Ticks& start, const Ticks& end) const = 0;
 221 };
 222 
 223 class ZStatPhaseCycle : public ZStatPhase {
 224 public:
 225   ZStatPhaseCycle(const char* name);
 226 
 227   virtual void register_start(const Ticks& start) const;
 228   virtual void register_end(const Ticks& start, const Ticks& end) const;
 229 };
 230 
 231 class ZStatPhasePause : public ZStatPhase {
 232 private:
 233   static Tickspan _max; // Max pause time
 234 
 235 public:
 236   ZStatPhasePause(const char* name);
 237 
 238   static const Tickspan& max();
 239 
 240   virtual void register_start(const Ticks& start) const;
 241   virtual void register_end(const Ticks& start, const Ticks& end) const;
 242 };
 243 
 244 class ZStatPhaseConcurrent : public ZStatPhase {
 245 public:
 246   ZStatPhaseConcurrent(const char* name);
 247 
 248   virtual void register_start(const Ticks& start) const;
 249   virtual void register_end(const Ticks& start, const Ticks& end) const;
 250 };
 251 
 252 class ZStatSubPhase : public ZStatPhase {
 253 public:
 254   ZStatSubPhase(const char* name);
 255 
 256   virtual void register_start(const Ticks& start) const;
 257   virtual void register_end(const Ticks& start, const Ticks& end) const;
 258 };
 259 
 260 class ZStatCriticalPhase : public ZStatPhase {
 261 private:
 262   const ZStatCounter _counter;
 263   const bool         _verbose;
 264 
 265 public:
 266   ZStatCriticalPhase(const char* name, bool verbose = true);
 267 
 268   virtual void register_start(const Ticks& start) const;
 269   virtual void register_end(const Ticks& start, const Ticks& end) const;
 270 };
 271 
 272 //
 273 // Stat timer
 274 //
 275 class ZStatTimerDisable : public StackObj {
 276 private:
 277   static THREAD_LOCAL uint32_t _active;
 278 
 279 public:
 280   ZStatTimerDisable() {
 281     _active++;
 282   }
 283 
 284   ~ZStatTimerDisable() {
 285     _active--;
 286   }
 287 
 288   static bool is_active() {
 289     return _active > 0;
 290   }
 291 };
 292 
 293 class ZStatTimer : public StackObj {
 294 private:
 295   const bool        _enabled;
 296   const ZStatPhase& _phase;
 297   const Ticks       _start;
 298 
 299 public:
 300   ZStatTimer(const ZStatPhase& phase) :
 301       _enabled(!ZStatTimerDisable::is_active()),
 302       _phase(phase),
 303       _start(Ticks::now()) {
 304     if (_enabled) {
 305       _phase.register_start(_start);
 306     }
 307   }
 308 
 309   ~ZStatTimer() {
 310     if (_enabled) {
 311       const Ticks end = Ticks::now();
 312       _phase.register_end(_start, end);
 313     }
 314   }
 315 };
 316 
 317 //
 318 // Stat sample/increment
 319 //
 320 void ZStatSample(const ZStatSampler& sampler, uint64_t value);
 321 void ZStatInc(const ZStatCounter& counter, uint64_t increment = 1);
 322 void ZStatInc(const ZStatUnsampledCounter& counter, uint64_t increment = 1);
 323 
 324 //
 325 // Stat allocation rate
 326 //
 327 class ZStatAllocRate : public AllStatic {
 328 private:
 329   static const ZStatUnsampledCounter _counter;
 330   static TruncatedSeq                _rate;     // B/s
 331   static TruncatedSeq                _rate_avg; // B/s
 332 
 333 public:
 334   static const uint64_t sample_window_sec = 1; // seconds
 335   static const uint64_t sample_hz         = 10;
 336 
 337   static const ZStatUnsampledCounter& counter();
 338   static uint64_t sample_and_reset();
 339 
 340   static double avg();
 341   static double avg_sd();
 342 };
 343 
 344 //
 345 // Stat thread
 346 //
 347 class ZStat : public ConcurrentGCThread {
 348 private:
 349   static const uint64_t sample_hz = 1;
 350 
 351   ZMetronome _metronome;
 352 
 353   void sample_and_collect(ZStatSamplerHistory* history) const;
 354   bool should_print(LogTargetHandle log) const;
 355   void print(LogTargetHandle log, const ZStatSamplerHistory* history) const;
 356 
 357 protected:
 358   virtual void run_service();
 359   virtual void stop_service();
 360 
 361 public:
 362   ZStat();
 363 };
 364 
 365 //
 366 // Stat cycle
 367 //
 368 class ZStatCycle : public AllStatic {
 369 private:
 370   static uint64_t  _nwarmup_cycles;
 371   static Ticks     _start_of_last;
 372   static Ticks     _end_of_last;
 373   static NumberSeq _normalized_duration;
 374 
 375 public:
 376   static void at_start();
 377   static void at_end(GCCause::Cause cause, double boost_factor);
 378 
 379   static bool is_warm();
 380   static uint64_t nwarmup_cycles();
 381 
 382   static bool is_normalized_duration_trustable();
 383   static const AbsSeq& normalized_duration();
 384 
 385   static double time_since_last();
 386 };
 387 
 388 //
 389 // Stat load
 390 //
 391 class ZStatLoad : public AllStatic {
 392 public:
 393   static void print();
 394 };
 395 
 396 //
 397 // Stat mark
 398 //
 399 class ZStatMark : public AllStatic {
 400 private:
 401   static size_t _nstripes;
 402   static size_t _nproactiveflush;
 403   static size_t _nterminateflush;
 404   static size_t _ntrycomplete;
 405   static size_t _ncontinue;
 406 
 407 public:
 408   static void set_at_mark_start(size_t nstripes);
 409   static void set_at_mark_end(size_t nproactiveflush,
 410                               size_t nterminateflush,
 411                               size_t ntrycomplete,
 412                               size_t ncontinue);
 413 
 414   static void print();
 415 };
 416 
 417 //
 418 // Stat relocation
 419 //
 420 class ZStatRelocation : public AllStatic {
 421 private:
 422   struct Group {
 423     size_t _npages;
 424     size_t _total;
 425     size_t _empty;
 426     size_t _compacting_from;
 427     size_t _compacting_to;
 428   };
 429 
 430   static Group _small;
 431   static Group _medium;
 432   static Group _large;
 433   static bool  _success;
 434 
 435   static void print(const char* name, const ZStatRelocation::Group& group);
 436 
 437 public:
 438   static void set_at_select_relocation_set(const ZRelocationSetSelectorGroupStats& small,
 439                                            const ZRelocationSetSelectorGroupStats& medium,
 440                                            const ZRelocationSetSelectorGroupStats& large);
 441   static void set_at_relocate_end(bool success);
 442 
 443   static void print();
 444 };
 445 
 446 //
 447 // Stat nmethods
 448 //
 449 class ZStatNMethods : public AllStatic {
 450 public:
 451   static void print();
 452 };
 453 
 454 //
 455 // Stat metaspace
 456 //
 457 class ZStatMetaspace : public AllStatic {
 458 public:
 459   static void print();
 460 };
 461 
 462 //
 463 // Stat references
 464 //
 465 class ZStatReferences : public AllStatic {
 466 private:
 467   static struct ZCount {
 468     size_t encountered;
 469     size_t discovered;
 470     size_t enqueued;
 471   } _soft, _weak, _final, _phantom;
 472 
 473   static void set(ZCount* count, size_t encountered, size_t discovered, size_t enqueued);
 474   static void print(const char* name, const ZCount& ref);
 475 
 476 public:
 477   static void set_soft(size_t encountered, size_t discovered, size_t enqueued);
 478   static void set_weak(size_t encountered, size_t discovered, size_t enqueued);
 479   static void set_final(size_t encountered, size_t discovered, size_t enqueued);
 480   static void set_phantom(size_t encountered, size_t discovered, size_t enqueued);
 481 
 482   static void print();
 483 };
 484 
 485 //
 486 // Stat heap
 487 //
 488 class ZStatHeap : public AllStatic {
 489 private:
 490   static struct ZAtInitialize {
 491     size_t min_capacity;
 492     size_t max_capacity;
 493     size_t max_reserve;
 494   } _at_initialize;
 495 
 496   static struct ZAtMarkStart {
 497     size_t soft_max_capacity;
 498     size_t capacity;
 499     size_t reserve;
 500     size_t used;
 501     size_t free;
 502   } _at_mark_start;
 503 
 504   static struct ZAtMarkEnd {
 505     size_t capacity;
 506     size_t reserve;
 507     size_t allocated;
 508     size_t used;
 509     size_t free;
 510     size_t live;
 511     size_t garbage;
 512   } _at_mark_end;
 513 
 514   static struct ZAtRelocateStart {
 515     size_t capacity;
 516     size_t reserve;
 517     size_t garbage;
 518     size_t allocated;
 519     size_t reclaimed;
 520     size_t used;
 521     size_t free;
 522   } _at_relocate_start;
 523 
 524   static struct ZAtRelocateEnd {
 525     size_t capacity;
 526     size_t capacity_high;
 527     size_t capacity_low;
 528     size_t reserve;
 529     size_t reserve_high;
 530     size_t reserve_low;
 531     size_t garbage;
 532     size_t allocated;
 533     size_t reclaimed;
 534     size_t used;
 535     size_t used_high;
 536     size_t used_low;
 537     size_t free;
 538     size_t free_high;
 539     size_t free_low;
 540   } _at_relocate_end;
 541 
 542   static size_t capacity_high();
 543   static size_t capacity_low();
 544   static size_t available(size_t used);
 545   static size_t reserve(size_t used);
 546   static size_t free(size_t used);
 547 
 548 public:
 549   static void set_at_initialize(size_t min_capacity,
 550                                 size_t max_capacity,
 551                                 size_t max_reserve);
 552   static void set_at_mark_start(size_t soft_max_capacity,
 553                                 size_t capacity,
 554                                 size_t used);
 555   static void set_at_mark_end(size_t capacity,
 556                               size_t allocated,
 557                               size_t used);
 558   static void set_at_select_relocation_set(const ZRelocationSetSelectorGroupStats& small,
 559                                            const ZRelocationSetSelectorGroupStats& medium,
 560                                            const ZRelocationSetSelectorGroupStats& large,
 561                                            size_t reclaimed);
 562   static void set_at_relocate_start(size_t capacity,
 563                                     size_t allocated,
 564                                     size_t used);
 565   static void set_at_relocate_end(size_t capacity,
 566                                   size_t allocated,
 567                                   size_t reclaimed,
 568                                   size_t used,
 569                                   size_t used_high,
 570                                   size_t used_low);
 571 
 572   static size_t max_capacity();
 573   static size_t used_at_mark_start();
 574   static size_t used_at_relocate_end();
 575 
 576   static void print();
 577 };
 578 
 579 #endif // SHARE_GC_Z_ZSTAT_HPP