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/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
35class ZPage;
36class ZStatSampler;
37class ZStatSamplerHistory;
38struct ZStatCounterData;
39struct ZStatSamplerData;
40
41//
42// Stat unit printers
43//
44typedef void (*ZStatUnitPrinter)(LogTargetHandle log, const ZStatSampler&, const ZStatSamplerHistory&);
45
46void ZStatUnitTime(LogTargetHandle log, const ZStatSampler& sampler, const ZStatSamplerHistory& history);
47void ZStatUnitBytes(LogTargetHandle log, const ZStatSampler& sampler, const ZStatSamplerHistory& history);
48void ZStatUnitThreads(LogTargetHandle log, const ZStatSampler& sampler, const ZStatSamplerHistory& history);
49void ZStatUnitBytesPerSecond(LogTargetHandle log, const ZStatSampler& sampler, const ZStatSamplerHistory& history);
50void ZStatUnitOpsPerSecond(LogTargetHandle log, const ZStatSampler& sampler, const ZStatSamplerHistory& history);
51
52//
53// Stat value
54//
55class ZStatValue {
56private:
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
65protected:
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
73public:
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//
84template <typename T>
85class ZStatIterableValue : public ZStatValue {
86private:
87 static uint32_t _count;
88 static T* _first;
89
90 T* _next;
91
92 T* insert() const;
93
94protected:
95 ZStatIterableValue(const char* group,
96 const char* name,
97 uint32_t size);
98
99public:
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//
116class ZStatSampler : public ZStatIterableValue<ZStatSampler> {
117private:
118 const ZStatUnitPrinter _printer;
119
120public:
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//
134class ZStatCounter : public ZStatIterableValue<ZStatCounter> {
135private:
136 const ZStatSampler _sampler;
137
138public:
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//
150class ZStatUnsampledCounter : public ZStatIterableValue<ZStatUnsampledCounter> {
151public:
152 ZStatUnsampledCounter(const char* name);
153
154 ZStatCounterData* get() const;
155 ZStatCounterData collect_and_reset() const;
156};
157
158//
159// Stat MMU (Minimum Mutator Utilization)
160//
161class ZStatMMUPause {
162private:
163 double _start;
164 double _end;
165
166public:
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
174class ZStatMMU {
175private:
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
190public:
191 static void register_pause(const Ticks& start, const Ticks& end);
192
193 static void print();
194};
195
196//
197// Stat phases
198//
199class ZStatPhase {
200private:
201 static ConcurrentGCTimer _timer;
202
203protected:
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
211public:
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
220class ZStatPhaseCycle : public ZStatPhase {
221public:
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
228class ZStatPhasePause : public ZStatPhase {
229private:
230 static Tickspan _max; // Max pause time
231
232public:
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
241class ZStatPhaseConcurrent : public ZStatPhase {
242public:
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
249class ZStatSubPhase : public ZStatPhase {
250public:
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
257class ZStatCriticalPhase : public ZStatPhase {
258private:
259 const ZStatCounter _counter;
260 const bool _verbose;
261
262public:
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//
272class ZStatTimerDisable : public StackObj {
273private:
274 static __thread uint32_t _active;
275
276public:
277 ZStatTimerDisable() {
278 _active++;
279 }
280
281 ~ZStatTimerDisable() {
282 _active--;
283 }
284
285 static bool is_active() {
286 return _active > 0;
287 }
288};
289
290class ZStatTimer : public StackObj {
291private:
292 const bool _enabled;
293 const ZStatPhase& _phase;
294 const Ticks _start;
295
296public:
297 ZStatTimer(const ZStatPhase& phase) :
298 _enabled(!ZStatTimerDisable::is_active()),
299 _phase(phase),
300 _start(Ticks::now()) {
301 if (_enabled) {
302 _phase.register_start(_start);
303 }
304 }
305
306 ~ZStatTimer() {
307 if (_enabled) {
308 const Ticks end = Ticks::now();
309 _phase.register_end(_start, end);
310 }
311 }
312};
313
314//
315// Stat sample/increment
316//
317void ZStatSample(const ZStatSampler& sampler, uint64_t value, bool trace = ZStatisticsForceTrace);
318void ZStatInc(const ZStatCounter& counter, uint64_t increment = 1, bool trace = ZStatisticsForceTrace);
319void ZStatInc(const ZStatUnsampledCounter& counter, uint64_t increment = 1);
320
321//
322// Stat allocation rate
323//
324class ZStatAllocRate : public AllStatic {
325private:
326 static const ZStatUnsampledCounter _counter;
327 static TruncatedSeq _rate; // B/s
328 static TruncatedSeq _rate_avg; // B/s
329
330public:
331 static const uint64_t sample_window_sec = 1; // seconds
332 static const uint64_t sample_hz = 10;
333
334 static const ZStatUnsampledCounter& counter();
335 static uint64_t sample_and_reset();
336
337 static double avg();
338 static double avg_sd();
339};
340
341//
342// Stat thread
343//
344class ZStat : public ConcurrentGCThread {
345private:
346 static const uint64_t sample_hz = 1;
347
348 ZMetronome _metronome;
349
350 void sample_and_collect(ZStatSamplerHistory* history) const;
351 bool should_print(LogTargetHandle log) const;
352 void print(LogTargetHandle log, const ZStatSamplerHistory* history) const;
353
354protected:
355 virtual void run_service();
356 virtual void stop_service();
357
358public:
359 ZStat();
360};
361
362//
363// Stat cycle
364//
365class ZStatCycle : public AllStatic {
366private:
367 static uint64_t _ncycles;
368 static Ticks _start_of_last;
369 static Ticks _end_of_last;
370 static NumberSeq _normalized_duration;
371
372public:
373 static void at_start();
374 static void at_end(double boost_factor);
375
376 static uint64_t ncycles();
377 static const AbsSeq& normalized_duration();
378 static double time_since_last();
379};
380
381//
382// Stat load
383//
384class ZStatLoad : public AllStatic {
385public:
386 static void print();
387};
388
389//
390// Stat mark
391//
392class ZStatMark : public AllStatic {
393private:
394 static size_t _nstripes;
395 static size_t _nproactiveflush;
396 static size_t _nterminateflush;
397 static size_t _ntrycomplete;
398 static size_t _ncontinue;
399
400public:
401 static void set_at_mark_start(size_t nstripes);
402 static void set_at_mark_end(size_t nproactiveflush,
403 size_t nterminateflush,
404 size_t ntrycomplete,
405 size_t ncontinue);
406
407 static void print();
408};
409
410//
411// Stat relocation
412//
413class ZStatRelocation : public AllStatic {
414private:
415 static size_t _relocating;
416 static bool _success;
417
418public:
419 static void set_at_select_relocation_set(size_t relocating);
420 static void set_at_relocate_end(bool success);
421
422 static void print();
423};
424
425//
426// Stat nmethods
427//
428class ZStatNMethods : public AllStatic {
429public:
430 static void print();
431};
432
433//
434// Stat metaspace
435//
436class ZStatMetaspace : public AllStatic {
437public:
438 static void print();
439};
440
441//
442// Stat references
443//
444class ZStatReferences : public AllStatic {
445private:
446 static struct ZCount {
447 size_t encountered;
448 size_t discovered;
449 size_t enqueued;
450 } _soft, _weak, _final, _phantom;
451
452 static void set(ZCount* count, size_t encountered, size_t discovered, size_t enqueued);
453 static void print(const char* name, const ZCount& ref);
454
455public:
456 static void set_soft(size_t encountered, size_t discovered, size_t enqueued);
457 static void set_weak(size_t encountered, size_t discovered, size_t enqueued);
458 static void set_final(size_t encountered, size_t discovered, size_t enqueued);
459 static void set_phantom(size_t encountered, size_t discovered, size_t enqueued);
460
461 static void print();
462};
463
464//
465// Stat heap
466//
467class ZStatHeap : public AllStatic {
468private:
469 static struct ZAtInitialize {
470 size_t min_capacity;
471 size_t max_capacity;
472 size_t max_reserve;
473 } _at_initialize;
474
475 static struct ZAtMarkStart {
476 size_t soft_max_capacity;
477 size_t capacity;
478 size_t reserve;
479 size_t used;
480 size_t free;
481 } _at_mark_start;
482
483 static struct ZAtMarkEnd {
484 size_t capacity;
485 size_t reserve;
486 size_t allocated;
487 size_t used;
488 size_t free;
489 size_t live;
490 size_t garbage;
491 } _at_mark_end;
492
493 static struct ZAtRelocateStart {
494 size_t capacity;
495 size_t reserve;
496 size_t garbage;
497 size_t allocated;
498 size_t reclaimed;
499 size_t used;
500 size_t free;
501 } _at_relocate_start;
502
503 static struct ZAtRelocateEnd {
504 size_t capacity;
505 size_t capacity_high;
506 size_t capacity_low;
507 size_t reserve;
508 size_t reserve_high;
509 size_t reserve_low;
510 size_t garbage;
511 size_t allocated;
512 size_t reclaimed;
513 size_t used;
514 size_t used_high;
515 size_t used_low;
516 size_t free;
517 size_t free_high;
518 size_t free_low;
519 } _at_relocate_end;
520
521 static size_t available(size_t used);
522 static size_t reserve(size_t used);
523 static size_t free(size_t used);
524
525public:
526 static void set_at_initialize(size_t min_capacity,
527 size_t max_capacity,
528 size_t max_reserve);
529 static void set_at_mark_start(size_t soft_max_capacity,
530 size_t capacity,
531 size_t used);
532 static void set_at_mark_end(size_t capacity,
533 size_t allocated,
534 size_t used);
535 static void set_at_select_relocation_set(size_t live,
536 size_t garbage,
537 size_t reclaimed);
538 static void set_at_relocate_start(size_t capacity,
539 size_t allocated,
540 size_t used);
541 static void set_at_relocate_end(size_t capacity,
542 size_t allocated,
543 size_t reclaimed,
544 size_t used,
545 size_t used_high,
546 size_t used_low);
547
548 static size_t max_capacity();
549 static size_t used_at_mark_start();
550 static size_t used_at_relocate_end();
551
552 static void print();
553};
554
555#endif // SHARE_GC_Z_ZSTAT_HPP
556