mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +02:00
6962947: shared TaskQueue statistics
Reviewed-by: tonyp, ysr
This commit is contained in:
parent
4efdcb87d1
commit
daf491a814
11 changed files with 236 additions and 137 deletions
|
@ -22,6 +22,72 @@
|
|||
*
|
||||
*/
|
||||
|
||||
// Simple TaskQueue stats that are collected by default in debug builds.
|
||||
|
||||
#if !defined(TASKQUEUE_STATS) && defined(ASSERT)
|
||||
#define TASKQUEUE_STATS 1
|
||||
#elif !defined(TASKQUEUE_STATS)
|
||||
#define TASKQUEUE_STATS 0
|
||||
#endif
|
||||
|
||||
#if TASKQUEUE_STATS
|
||||
#define TASKQUEUE_STATS_ONLY(code) code
|
||||
#else
|
||||
#define TASKQUEUE_STATS_ONLY(code)
|
||||
#endif // TASKQUEUE_STATS
|
||||
|
||||
#if TASKQUEUE_STATS
|
||||
class TaskQueueStats {
|
||||
public:
|
||||
enum StatId {
|
||||
push, // number of taskqueue pushes
|
||||
pop, // number of taskqueue pops
|
||||
pop_slow, // subset of taskqueue pops that were done slow-path
|
||||
steal_attempt, // number of taskqueue steal attempts
|
||||
steal, // number of taskqueue steals
|
||||
overflow, // number of overflow pushes
|
||||
overflow_max_len, // max length of overflow stack
|
||||
last_stat_id
|
||||
};
|
||||
|
||||
public:
|
||||
inline TaskQueueStats() { reset(); }
|
||||
|
||||
inline void record_push() { ++_stats[push]; }
|
||||
inline void record_pop() { ++_stats[pop]; }
|
||||
inline void record_pop_slow() { record_pop(); ++_stats[pop_slow]; }
|
||||
inline void record_steal(bool success);
|
||||
inline void record_overflow(size_t new_length);
|
||||
|
||||
inline size_t get(StatId id) const { return _stats[id]; }
|
||||
inline const size_t* get() const { return _stats; }
|
||||
|
||||
inline void reset();
|
||||
|
||||
static void print_header(unsigned int line, outputStream* const stream = tty,
|
||||
unsigned int width = 10);
|
||||
void print(outputStream* const stream = tty, unsigned int width = 10) const;
|
||||
|
||||
private:
|
||||
size_t _stats[last_stat_id];
|
||||
static const char * const _names[last_stat_id];
|
||||
};
|
||||
|
||||
void TaskQueueStats::record_steal(bool success) {
|
||||
++_stats[steal_attempt];
|
||||
if (success) ++_stats[steal];
|
||||
}
|
||||
|
||||
void TaskQueueStats::record_overflow(size_t new_len) {
|
||||
++_stats[overflow];
|
||||
if (new_len > _stats[overflow_max_len]) _stats[overflow_max_len] = new_len;
|
||||
}
|
||||
|
||||
void TaskQueueStats::reset() {
|
||||
memset(_stats, 0, sizeof(_stats));
|
||||
}
|
||||
#endif // TASKQUEUE_STATS
|
||||
|
||||
template <unsigned int N>
|
||||
class TaskQueueSuper: public CHeapObj {
|
||||
protected:
|
||||
|
@ -135,6 +201,8 @@ public:
|
|||
|
||||
// Total size of queue.
|
||||
static const uint total_size() { return N; }
|
||||
|
||||
TASKQUEUE_STATS_ONLY(TaskQueueStats stats;)
|
||||
};
|
||||
|
||||
template<class E, unsigned int N = TASKQUEUE_SIZE>
|
||||
|
@ -152,6 +220,7 @@ protected:
|
|||
public:
|
||||
using TaskQueueSuper<N>::max_elems;
|
||||
using TaskQueueSuper<N>::size;
|
||||
TASKQUEUE_STATS_ONLY(using TaskQueueSuper<N>::stats;)
|
||||
|
||||
private:
|
||||
// Slow paths for push, pop_local. (pop_global has no fast path.)
|
||||
|
@ -224,14 +293,14 @@ bool GenericTaskQueue<E, N>::push_slow(E t, uint dirty_n_elems) {
|
|||
// g++ complains if the volatile result of the assignment is unused.
|
||||
const_cast<E&>(_elems[localBot] = t);
|
||||
OrderAccess::release_store(&_bottom, increment_index(localBot));
|
||||
TASKQUEUE_STATS_ONLY(stats.record_push());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<class E, unsigned int N>
|
||||
bool GenericTaskQueue<E, N>::
|
||||
pop_local_slow(uint localBot, Age oldAge) {
|
||||
bool GenericTaskQueue<E, N>::pop_local_slow(uint localBot, Age oldAge) {
|
||||
// This queue was observed to contain exactly one element; either this
|
||||
// thread will claim it, or a competing "pop_global". In either case,
|
||||
// the queue will be logically empty afterwards. Create a new Age value
|
||||
|
@ -251,6 +320,7 @@ pop_local_slow(uint localBot, Age oldAge) {
|
|||
if (tempAge == oldAge) {
|
||||
// We win.
|
||||
assert(dirty_size(localBot, _age.top()) != N - 1, "sanity");
|
||||
TASKQUEUE_STATS_ONLY(stats.record_pop_slow());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -306,6 +376,8 @@ public:
|
|||
typedef GrowableArray<E> overflow_t;
|
||||
typedef GenericTaskQueue<E, N> taskqueue_t;
|
||||
|
||||
TASKQUEUE_STATS_ONLY(using taskqueue_t::stats;)
|
||||
|
||||
OverflowTaskQueue();
|
||||
~OverflowTaskQueue();
|
||||
void initialize();
|
||||
|
@ -356,6 +428,7 @@ bool OverflowTaskQueue<E, N>::push(E t)
|
|||
{
|
||||
if (!taskqueue_t::push(t)) {
|
||||
overflow_stack()->push(t);
|
||||
TASKQUEUE_STATS_ONLY(stats.record_overflow(overflow_stack()->length()));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -424,9 +497,13 @@ GenericTaskQueueSet<T>::queue(uint i) {
|
|||
|
||||
template<class T> bool
|
||||
GenericTaskQueueSet<T>::steal(uint queue_num, int* seed, E& t) {
|
||||
for (uint i = 0; i < 2 * _n; i++)
|
||||
if (steal_best_of_2(queue_num, seed, t))
|
||||
for (uint i = 0; i < 2 * _n; i++) {
|
||||
if (steal_best_of_2(queue_num, seed, t)) {
|
||||
TASKQUEUE_STATS_ONLY(queue(queue_num)->stats.record_steal(true));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
TASKQUEUE_STATS_ONLY(queue(queue_num)->stats.record_steal(false));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -574,6 +651,7 @@ GenericTaskQueue<E, N>::push(E t) {
|
|||
// g++ complains if the volatile result of the assignment is unused.
|
||||
const_cast<E&>(_elems[localBot] = t);
|
||||
OrderAccess::release_store(&_bottom, increment_index(localBot));
|
||||
TASKQUEUE_STATS_ONLY(stats.record_push());
|
||||
return true;
|
||||
} else {
|
||||
return push_slow(t, dirty_n_elems);
|
||||
|
@ -603,6 +681,7 @@ GenericTaskQueue<E, N>::pop_local(E& t) {
|
|||
idx_t tp = _age.top(); // XXX
|
||||
if (size(localBot, tp) > 0) {
|
||||
assert(dirty_size(localBot, tp) != N - 1, "sanity");
|
||||
TASKQUEUE_STATS_ONLY(stats.record_pop());
|
||||
return true;
|
||||
} else {
|
||||
// Otherwise, the queue contained exactly one element; we take the slow
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue