< prev index next > src/hotspot/share/runtime/perfData.hpp
Print this page
/*
- * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2024, 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.
public:
inline void inc() { (*(jlong*)_valuep)++; }
inline void inc(jlong val) { (*(jlong*)_valuep) += val; }
inline void dec(jlong val) { inc(-val); }
+ inline void reset() { (*(jlong*)_valuep) = 0; }
};
/*
* The PerfLongCounter class, and its alias PerfCounter, implement
* a PerfData subtype that holds a jlong data value that can (should)
// some form of iterator to provide a cleaner abstraction for
// iteration over the container.
inline PerfData* at(int index);
};
+ class PerfTickCounters : public CHeapObj<mtInternal> {
+ private:
+ const char* _name;
+ PerfCounter* const _elapsed_counter;
+ PerfCounter* const _thread_counter;
+ public:
+ PerfTickCounters(const char* name, PerfCounter* elapsed_counter, PerfCounter* thread_counter) :
+ _name(name), _elapsed_counter(elapsed_counter), _thread_counter(thread_counter) {
+ }
+
+ const char* name() { return _name; }
+
+ PerfCounter* elapsed_counter() const {
+ return _elapsed_counter;
+ }
+ long elapsed_counter_value() const {
+ return _elapsed_counter->get_value();
+ }
+ inline jlong elapsed_counter_value_ms() const;
+ inline jlong elapsed_counter_value_us() const;
+
+ PerfCounter* thread_counter() const {
+ return _thread_counter;
+ }
+ jlong thread_counter_value() const {
+ return _thread_counter->get_value();
+ }
+ inline jlong thread_counter_value_ms() const;
+ inline jlong thread_counter_value_us() const;
+
+ void reset() {
+ _elapsed_counter->reset();
+ _thread_counter->reset();
+ }
+ };
/*
* The PerfDataManager class is responsible for creating PerfData
* subtypes via a set a factory methods and for managing lists
* of the various PerfData types.
PerfData::Units u,
PerfSampleHelper* sh, TRAPS) {
return create_long_counter(ns, name, u, sh, THREAD);
}
+ static PerfTickCounters* create_tick_counters(CounterNS ns,
+ const char* counter_name,
+ const char* elapsed_counter_name,
+ const char* thread_counter_name,
+ PerfData::Units u, TRAPS) {
+ PerfCounter* elapsed_counter = create_long_counter(ns, elapsed_counter_name, u, (jlong)0, THREAD);
+ PerfCounter* thread_counter = create_long_counter(ns, thread_counter_name, u, (jlong)0, THREAD);
+
+ PerfTickCounters* counters = new PerfTickCounters(counter_name, elapsed_counter, thread_counter);
+ return counters;
+ }
+
static void destroy();
static bool has_PerfData() { return _has_PerfData; }
};
// Useful macros to create the performance counters
#define NEWPERFBYTECOUNTER(counter, counter_ns, counter_name) \
{counter = PerfDataManager::create_counter(counter_ns, counter_name, \
PerfData::U_Bytes,CHECK);}
+ #define NEWPERFTICKCOUNTERS(counter, counter_ns, counter_name) \
+ {counter = PerfDataManager::create_tick_counters(counter_ns, counter_name, counter_name "_elapsed_time", \
+ counter_name "_thread_time", PerfData::U_Ticks,CHECK);}
+
// Utility Classes
- /*
- * this class will administer a PerfCounter used as a time accumulator
+ /* PerfTraceElapsedTime and PerfTraceThreadTime will administer a PerfCounter used as a time accumulator
* for a basic block much like the TraceTime class.
+ * PerfTraceElapsedTime uses elapsedTimer to measure time which reflects the elapsed time,
+ * and PerfTraceThreadTime uses ThreadTimer which reflects thread cpu time.
*
* Example:
*
* static PerfCounter* my_time_counter = PerfDataManager::create_counter("my.time.counter", PerfData::U_Ticks, 0LL, CHECK);
*
* {
- * PerfTraceTime ptt(my_time_counter);
+ * PerfTraceElapsedTime ptt(my_time_counter);
* // perform the operation you want to measure
* }
*
* Note: use of this class does not need to occur within a guarded
* block. The UsePerfData guard is used with the implementation
* of this class.
*/
- class PerfTraceTime : public StackObj {
+ class PerfTraceTimeBase : public StackObj {
+ friend class PerfPauseTimer;
+ private:
+ BaseTimer* _t;
+ protected:
+ PerfLongCounter* _counter;
+
+ public:
+ inline PerfTraceTimeBase(BaseTimer* t, PerfLongCounter* counter) : _t(t), _counter(counter) {}
+
+ ~PerfTraceTimeBase();
+
+ jlong active_ticks() { return _t->active_ticks(); }
+
+ const char* name() { return _counter->name(); }
+ BaseTimer* timer() { return _t; }
+ };
+
+ class PerfTraceElapsedTime: public PerfTraceTimeBase {
protected:
elapsedTimer _t;
- PerfLongCounter* _timerp;
public:
- inline PerfTraceTime(PerfLongCounter* timerp) : _timerp(timerp) {
- if (!UsePerfData || timerp == nullptr) { return; }
+ inline PerfTraceElapsedTime(PerfCounter* counter) : PerfTraceTimeBase(&_t, counter) {
+ if (!UsePerfData || counter == nullptr) { return; }
+ _t.start();
+ }
+ };
+
+ class PerfTraceThreadTime: public PerfTraceTimeBase {
+ protected:
+ ThreadTimer _t;
+
+ public:
+ inline PerfTraceThreadTime(PerfCounter* counter) : PerfTraceTimeBase(&_t, counter) {
+ if (!UsePerfData || !TraceThreadTime || counter == nullptr) { return; }
_t.start();
}
+ };
+
+ // PerfTraceTime is a utility class to provide the ability to measure both elapsed and thread cpu time using a single object.
+ class PerfTraceTime : public StackObj {
+ friend class PerfPauseTimer;
+ private:
+ PerfTickCounters* _counters;
+ PerfTraceElapsedTime _elapsed_timer;
+ PerfTraceThreadTime _thread_timer;
+
+ public:
+ inline PerfTraceTime(PerfTickCounters* counters, bool is_on = true):
+ _counters(counters),
+ _elapsed_timer(counters != nullptr ? counters->elapsed_counter() : nullptr),
+ _thread_timer(counters != nullptr ? counters->thread_counter() : nullptr) {}
+
+ const char* name() { return _counters->name(); }
+ PerfTraceTimeBase* elapsed_timer() { return &_elapsed_timer; }
+ PerfTraceTimeBase* thread_timer() { return &_thread_timer; }
- const char* name() const {
- assert(_timerp != nullptr, "sanity");
- return _timerp->name();
+ jlong elapsed_timer_active_ticks() {
+ return _elapsed_timer.active_ticks();
}
- ~PerfTraceTime() {
- if (!UsePerfData || !_t.is_active()) { return; }
- _t.stop();
- _timerp->inc(_t.ticks());
+ jlong thread_timer_active_ticks() {
+ return _thread_timer.active_ticks();
}
};
- /* The PerfTraceTimedEvent class is responsible for counting the
+ class PerfPauseTimerBase : public StackObj {
+ protected:
+ bool _is_active;
+ BaseTimer* _timer;
+
+ public:
+ inline PerfPauseTimerBase(PerfTraceTimeBase* timer, bool is_on) : _is_active(false), _timer(nullptr) {
+ _is_active = (is_on && timer != nullptr);
+ if (UsePerfData && _is_active) {
+ _timer = timer->timer();
+ _timer->stop(); // pause
+ }
+ }
+
+ inline ~PerfPauseTimerBase() {
+ if (UsePerfData && _is_active) {
+ assert(_timer != nullptr, "");
+ _timer->start(); // resume
+ }
+ }
+ };
+
+ class PerfPauseTimer : public StackObj {
+ private:
+ PerfPauseTimerBase _elapsed_timer_pause;
+ PerfPauseTimerBase _thread_timer_pause;
+
+ public:
+ inline PerfPauseTimer(PerfTraceTime* timer, bool is_on) :
+ _elapsed_timer_pause(timer != nullptr ? timer->elapsed_timer() : nullptr, is_on),
+ _thread_timer_pause(timer != nullptr ? timer->thread_timer() : nullptr, is_on) {}
+ };
+
+ /* The PerfTraceElapsedTimeEvent class is responsible for counting the
* occurrence of some event and measuring the elapsed time of
* the event in two separate PerfCounter instances.
*
* Example:
*
* static PerfCounter* my_time_counter = PerfDataManager::create_counter("my.time.counter", PerfData::U_Ticks, CHECK);
* static PerfCounter* my_event_counter = PerfDataManager::create_counter("my.event.counter", PerfData::U_Events, CHECK);
*
* {
- * PerfTraceTimedEvent ptte(my_time_counter, my_event_counter);
+ * PerfTraceElapsedTimeEvent ptte(my_time_counter, my_event_counter);
* // perform the operation you want to count and measure
* }
*
* Note: use of this class does not need to occur within a guarded
* block. The UsePerfData guard is used with the implementation
* of this class.
*
+ * Similarly, PerfTraceThreadTimeEvent can count the occurrence of some event and measure the thread cpu time of the event.
+ * PerfTraceTimedEvent can count the occurrence of some event and measure both the elapsed time and the thread cpu time of the event.
*/
- class PerfTraceTimedEvent : public PerfTraceTime {
-
+ class PerfTraceElapsedTimeEvent: public PerfTraceElapsedTime {
protected:
PerfLongCounter* _eventp;
public:
- inline PerfTraceTimedEvent(PerfLongCounter* timerp, PerfLongCounter* eventp): PerfTraceTime(timerp), _eventp(eventp) {
- if (!UsePerfData || timerp == nullptr) { return; }
+ inline PerfTraceElapsedTimeEvent(PerfCounter* counter, PerfLongCounter* eventp) : PerfTraceElapsedTime(counter), _eventp(eventp) {
+ if (!UsePerfData || counter == nullptr) return;
_eventp->inc();
}
+ };
+
+ class PerfTraceThreadTimeEvent: public PerfTraceThreadTime {
+ protected:
+ PerfLongCounter* _eventp;
+ public:
+ inline PerfTraceThreadTimeEvent(PerfCounter* counter, PerfLongCounter* eventp) : PerfTraceThreadTime(counter), _eventp(eventp) {
+ if (!UsePerfData || counter == nullptr) return;
+ _eventp->inc();
+ }
};
+ class PerfTraceTimedEvent : public PerfTraceTime {
+ protected:
+ PerfLongCounter* _eventp;
+
+ public:
+ inline PerfTraceTimedEvent(PerfTickCounters* counters, PerfLongCounter* eventp, bool is_on = true) : PerfTraceTime(counters, is_on), _eventp(eventp) {
+ if (!UsePerfData || !is_on || counters == nullptr) return;
+ _eventp->inc();
+ }
+ };
#endif // SHARE_RUNTIME_PERFDATA_HPP
< prev index next >