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