blob: 4983e5fcab69fe4757b092fca31054ed0157fdfd [file] [log] [blame]
/*
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#ifndef SHARE_GC_X_XSTAT_HPP
#define SHARE_GC_X_XSTAT_HPP
#include "gc/shared/concurrentGCThread.hpp"
#include "gc/shared/gcCause.hpp"
#include "gc/shared/gcTimer.hpp"
#include "gc/x/xMetronome.hpp"
#include "logging/logHandle.hpp"
#include "memory/allocation.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/numberSeq.hpp"
#include "utilities/ticks.hpp"
class XPage;
class XPageAllocatorStats;
class XRelocationSetSelectorGroupStats;
class XRelocationSetSelectorStats;
class XStatSampler;
class XStatSamplerHistory;
struct XStatCounterData;
struct XStatSamplerData;
//
// Stat unit printers
//
typedef void (*XStatUnitPrinter)(LogTargetHandle log, const XStatSampler&, const XStatSamplerHistory&);
void XStatUnitTime(LogTargetHandle log, const XStatSampler& sampler, const XStatSamplerHistory& history);
void XStatUnitBytes(LogTargetHandle log, const XStatSampler& sampler, const XStatSamplerHistory& history);
void XStatUnitThreads(LogTargetHandle log, const XStatSampler& sampler, const XStatSamplerHistory& history);
void XStatUnitBytesPerSecond(LogTargetHandle log, const XStatSampler& sampler, const XStatSamplerHistory& history);
void XStatUnitOpsPerSecond(LogTargetHandle log, const XStatSampler& sampler, const XStatSamplerHistory& history);
//
// Stat value
//
class XStatValue {
private:
static uintptr_t _base;
static uint32_t _cpu_offset;
const char* const _group;
const char* const _name;
const uint32_t _id;
const uint32_t _offset;
protected:
XStatValue(const char* group,
const char* name,
uint32_t id,
uint32_t size);
template <typename T> T* get_cpu_local(uint32_t cpu) const;
public:
static void initialize();
const char* group() const;
const char* name() const;
uint32_t id() const;
};
//
// Stat iterable value
//
template <typename T>
class XStatIterableValue : public XStatValue {
private:
static uint32_t _count;
static T* _first;
T* _next;
T* insert() const;
protected:
XStatIterableValue(const char* group,
const char* name,
uint32_t size);
public:
static void sort();
static uint32_t count() {
return _count;
}
static T* first() {
return _first;
}
T* next() const {
return _next;
}
};
template <typename T> uint32_t XStatIterableValue<T>::_count = 0;
template <typename T> T* XStatIterableValue<T>::_first = nullptr;
//
// Stat sampler
//
class XStatSampler : public XStatIterableValue<XStatSampler> {
private:
const XStatUnitPrinter _printer;
public:
XStatSampler(const char* group,
const char* name,
XStatUnitPrinter printer);
XStatSamplerData* get() const;
XStatSamplerData collect_and_reset() const;
XStatUnitPrinter printer() const;
};
//
// Stat counter
//
class XStatCounter : public XStatIterableValue<XStatCounter> {
private:
const XStatSampler _sampler;
public:
XStatCounter(const char* group,
const char* name,
XStatUnitPrinter printer);
XStatCounterData* get() const;
void sample_and_reset() const;
};
//
// Stat unsampled counter
//
class XStatUnsampledCounter : public XStatIterableValue<XStatUnsampledCounter> {
public:
XStatUnsampledCounter(const char* name);
XStatCounterData* get() const;
XStatCounterData collect_and_reset() const;
};
//
// Stat MMU (Minimum Mutator Utilization)
//
class XStatMMUPause {
private:
double _start;
double _end;
public:
XStatMMUPause();
XStatMMUPause(const Ticks& start, const Ticks& end);
double end() const;
double overlap(double start, double end) const;
};
class XStatMMU {
private:
static size_t _next;
static size_t _npauses;
static XStatMMUPause _pauses[200]; // Record the last 200 pauses
static double _mmu_2ms;
static double _mmu_5ms;
static double _mmu_10ms;
static double _mmu_20ms;
static double _mmu_50ms;
static double _mmu_100ms;
static const XStatMMUPause& pause(size_t index);
static double calculate_mmu(double time_slice);
public:
static void register_pause(const Ticks& start, const Ticks& end);
static void print();
};
//
// Stat phases
//
class XStatPhase {
private:
static ConcurrentGCTimer _timer;
protected:
const XStatSampler _sampler;
XStatPhase(const char* group, const char* name);
void log_start(LogTargetHandle log, bool thread = false) const;
void log_end(LogTargetHandle log, const Tickspan& duration, bool thread = false) const;
public:
static ConcurrentGCTimer* timer();
const char* name() const;
virtual void register_start(const Ticks& start) const = 0;
virtual void register_end(const Ticks& start, const Ticks& end) const = 0;
};
class XStatPhaseCycle : public XStatPhase {
public:
XStatPhaseCycle(const char* name);
virtual void register_start(const Ticks& start) const;
virtual void register_end(const Ticks& start, const Ticks& end) const;
};
class XStatPhasePause : public XStatPhase {
private:
static Tickspan _max; // Max pause time
public:
XStatPhasePause(const char* name);
static const Tickspan& max();
virtual void register_start(const Ticks& start) const;
virtual void register_end(const Ticks& start, const Ticks& end) const;
};
class XStatPhaseConcurrent : public XStatPhase {
public:
XStatPhaseConcurrent(const char* name);
virtual void register_start(const Ticks& start) const;
virtual void register_end(const Ticks& start, const Ticks& end) const;
};
class XStatSubPhase : public XStatPhase {
public:
XStatSubPhase(const char* name);
virtual void register_start(const Ticks& start) const;
virtual void register_end(const Ticks& start, const Ticks& end) const;
};
class XStatCriticalPhase : public XStatPhase {
private:
const XStatCounter _counter;
const bool _verbose;
public:
XStatCriticalPhase(const char* name, bool verbose = true);
virtual void register_start(const Ticks& start) const;
virtual void register_end(const Ticks& start, const Ticks& end) const;
};
//
// Stat timer
//
class XStatTimerDisable : public StackObj {
private:
static THREAD_LOCAL uint32_t _active;
public:
XStatTimerDisable() {
_active++;
}
~XStatTimerDisable() {
_active--;
}
static bool is_active() {
return _active > 0;
}
};
class XStatTimer : public StackObj {
private:
const bool _enabled;
const XStatPhase& _phase;
const Ticks _start;
public:
XStatTimer(const XStatPhase& phase) :
_enabled(!XStatTimerDisable::is_active()),
_phase(phase),
_start(Ticks::now()) {
if (_enabled) {
_phase.register_start(_start);
}
}
~XStatTimer() {
if (_enabled) {
const Ticks end = Ticks::now();
_phase.register_end(_start, end);
}
}
};
//
// Stat sample/increment
//
void XStatSample(const XStatSampler& sampler, uint64_t value);
void XStatInc(const XStatCounter& counter, uint64_t increment = 1);
void XStatInc(const XStatUnsampledCounter& counter, uint64_t increment = 1);
//
// Stat allocation rate
//
class XStatAllocRate : public AllStatic {
private:
static const XStatUnsampledCounter _counter;
static TruncatedSeq _samples;
static TruncatedSeq _rate;
public:
static const uint64_t sample_hz = 10;
static const XStatUnsampledCounter& counter();
static uint64_t sample_and_reset();
static double predict();
static double avg();
static double sd();
};
//
// Stat thread
//
class XStat : public ConcurrentGCThread {
private:
static const uint64_t sample_hz = 1;
XMetronome _metronome;
void sample_and_collect(XStatSamplerHistory* history) const;
bool should_print(LogTargetHandle log) const;
void print(LogTargetHandle log, const XStatSamplerHistory* history) const;
protected:
virtual void run_service();
virtual void stop_service();
public:
XStat();
};
//
// Stat cycle
//
class XStatCycle : public AllStatic {
private:
static uint64_t _nwarmup_cycles;
static Ticks _start_of_last;
static Ticks _end_of_last;
static NumberSeq _serial_time;
static NumberSeq _parallelizable_time;
static uint _last_active_workers;
public:
static void at_start();
static void at_end(GCCause::Cause cause, uint active_workers);
static bool is_warm();
static uint64_t nwarmup_cycles();
static bool is_time_trustable();
static const AbsSeq& serial_time();
static const AbsSeq& parallelizable_time();
static uint last_active_workers();
static double time_since_last();
};
//
// Stat workers
//
class XStatWorkers : public AllStatic {
private:
static Ticks _start_of_last;
static Tickspan _accumulated_duration;
public:
static void at_start();
static void at_end();
static double get_and_reset_duration();
};
//
// Stat load
//
class XStatLoad : public AllStatic {
public:
static void print();
};
//
// Stat mark
//
class XStatMark : public AllStatic {
private:
static size_t _nstripes;
static size_t _nproactiveflush;
static size_t _nterminateflush;
static size_t _ntrycomplete;
static size_t _ncontinue;
static size_t _mark_stack_usage;
public:
static void set_at_mark_start(size_t nstripes);
static void set_at_mark_end(size_t nproactiveflush,
size_t nterminateflush,
size_t ntrycomplete,
size_t ncontinue);
static void set_at_mark_free(size_t mark_stack_usage);
static void print();
};
//
// Stat relocation
//
class XStatRelocation : public AllStatic {
private:
static XRelocationSetSelectorStats _selector_stats;
static size_t _forwarding_usage;
static size_t _small_in_place_count;
static size_t _medium_in_place_count;
static void print(const char* name,
const XRelocationSetSelectorGroupStats& selector_group,
size_t in_place_count);
public:
static void set_at_select_relocation_set(const XRelocationSetSelectorStats& selector_stats);
static void set_at_install_relocation_set(size_t forwarding_usage);
static void set_at_relocate_end(size_t small_in_place_count, size_t medium_in_place_count);
static void print();
};
//
// Stat nmethods
//
class XStatNMethods : public AllStatic {
public:
static void print();
};
//
// Stat metaspace
//
class XStatMetaspace : public AllStatic {
public:
static void print();
};
//
// Stat references
//
class XStatReferences : public AllStatic {
private:
static struct XCount {
size_t encountered;
size_t discovered;
size_t enqueued;
} _soft, _weak, _final, _phantom;
static void set(XCount* count, size_t encountered, size_t discovered, size_t enqueued);
static void print(const char* name, const XCount& ref);
public:
static void set_soft(size_t encountered, size_t discovered, size_t enqueued);
static void set_weak(size_t encountered, size_t discovered, size_t enqueued);
static void set_final(size_t encountered, size_t discovered, size_t enqueued);
static void set_phantom(size_t encountered, size_t discovered, size_t enqueued);
static void print();
};
//
// Stat heap
//
class XStatHeap : public AllStatic {
private:
static struct XAtInitialize {
size_t min_capacity;
size_t max_capacity;
} _at_initialize;
static struct XAtMarkStart {
size_t soft_max_capacity;
size_t capacity;
size_t free;
size_t used;
} _at_mark_start;
static struct XAtMarkEnd {
size_t capacity;
size_t free;
size_t used;
size_t live;
size_t allocated;
size_t garbage;
} _at_mark_end;
static struct XAtRelocateStart {
size_t capacity;
size_t free;
size_t used;
size_t allocated;
size_t garbage;
size_t reclaimed;
} _at_relocate_start;
static struct XAtRelocateEnd {
size_t capacity;
size_t capacity_high;
size_t capacity_low;
size_t free;
size_t free_high;
size_t free_low;
size_t used;
size_t used_high;
size_t used_low;
size_t allocated;
size_t garbage;
size_t reclaimed;
} _at_relocate_end;
static size_t capacity_high();
static size_t capacity_low();
static size_t free(size_t used);
static size_t allocated(size_t used, size_t reclaimed);
static size_t garbage(size_t reclaimed);
public:
static void set_at_initialize(const XPageAllocatorStats& stats);
static void set_at_mark_start(const XPageAllocatorStats& stats);
static void set_at_mark_end(const XPageAllocatorStats& stats);
static void set_at_select_relocation_set(const XRelocationSetSelectorStats& stats);
static void set_at_relocate_start(const XPageAllocatorStats& stats);
static void set_at_relocate_end(const XPageAllocatorStats& stats, size_t non_worker_relocated);
static size_t max_capacity();
static size_t used_at_mark_start();
static size_t used_at_relocate_end();
static void print();
};
#endif // SHARE_GC_X_XSTAT_HPP