2014-01-03 08:20:13 +00:00
|
|
|
#pragma once
|
|
|
|
|
2018-06-20 17:49:52 +00:00
|
|
|
#include <Common/VariableContext.h>
|
2021-11-08 13:38:31 +00:00
|
|
|
#include "base/types.h"
|
2016-07-31 03:53:16 +00:00
|
|
|
#include <atomic>
|
2018-02-01 17:55:08 +00:00
|
|
|
#include <memory>
|
2022-06-27 21:00:37 +00:00
|
|
|
#include <cstddef>
|
2014-01-03 08:20:13 +00:00
|
|
|
|
2016-10-24 02:02:37 +00:00
|
|
|
/** Implements global counters for various events happening in the application
|
|
|
|
* - for high level profiling.
|
|
|
|
* See .cpp for list of events.
|
2014-01-03 08:20:13 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
namespace ProfileEvents
|
|
|
|
{
|
2016-10-24 02:02:37 +00:00
|
|
|
/// Event identifier (index in array).
|
|
|
|
using Event = size_t;
|
|
|
|
using Count = size_t;
|
2021-11-08 13:38:31 +00:00
|
|
|
using Increment = Int64;
|
2018-02-01 17:55:08 +00:00
|
|
|
using Counter = std::atomic<Count>;
|
2018-06-01 19:39:32 +00:00
|
|
|
class Counters;
|
|
|
|
|
|
|
|
/// Counters - how many times each event happened
|
|
|
|
extern Counters global_counters;
|
2018-02-01 17:55:08 +00:00
|
|
|
|
2018-05-31 15:54:08 +00:00
|
|
|
class Counters
|
2018-02-01 17:55:08 +00:00
|
|
|
{
|
|
|
|
Counter * counters = nullptr;
|
|
|
|
std::unique_ptr<Counter[]> counters_holder;
|
2018-06-01 19:39:32 +00:00
|
|
|
/// Used to propagate increments
|
|
|
|
Counters * parent = nullptr;
|
2018-02-01 17:55:08 +00:00
|
|
|
|
2018-05-31 15:54:08 +00:00
|
|
|
public:
|
|
|
|
|
2018-06-09 15:29:08 +00:00
|
|
|
VariableContext level = VariableContext::Thread;
|
2018-02-01 17:55:08 +00:00
|
|
|
|
2018-06-01 19:39:32 +00:00
|
|
|
/// By default, any instance have to increment global counters
|
2022-03-11 21:47:28 +00:00
|
|
|
explicit Counters(VariableContext level_ = VariableContext::Thread, Counters * parent_ = &global_counters);
|
2018-02-01 17:55:08 +00:00
|
|
|
|
|
|
|
/// Global level static initializer
|
2022-03-11 21:47:28 +00:00
|
|
|
explicit Counters(Counter * allocated_counters) noexcept
|
2018-11-26 00:56:50 +00:00
|
|
|
: counters(allocated_counters), parent(nullptr), level(VariableContext::Global) {}
|
2018-02-01 17:55:08 +00:00
|
|
|
|
2018-06-20 17:49:52 +00:00
|
|
|
Counter & operator[] (Event event)
|
|
|
|
{
|
|
|
|
return counters[event];
|
|
|
|
}
|
|
|
|
|
|
|
|
const Counter & operator[] (Event event) const
|
2018-02-01 17:55:08 +00:00
|
|
|
{
|
|
|
|
return counters[event];
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void increment(Event event, Count amount = 1)
|
|
|
|
{
|
|
|
|
Counters * current = this;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
current->counters[event].fetch_add(amount, std::memory_order_relaxed);
|
|
|
|
current = current->parent;
|
|
|
|
} while (current != nullptr);
|
|
|
|
}
|
|
|
|
|
2021-10-11 15:56:23 +00:00
|
|
|
struct Snapshot
|
|
|
|
{
|
|
|
|
Snapshot();
|
2021-11-08 09:40:31 +00:00
|
|
|
Snapshot(Snapshot &&) = default;
|
2021-10-11 15:56:23 +00:00
|
|
|
|
2021-11-08 13:38:31 +00:00
|
|
|
Count operator[] (Event event) const noexcept
|
2021-10-11 15:56:23 +00:00
|
|
|
{
|
|
|
|
return counters_holder[event];
|
|
|
|
}
|
|
|
|
|
2021-11-08 09:40:31 +00:00
|
|
|
Snapshot & operator=(Snapshot &&) = default;
|
2021-10-11 15:56:23 +00:00
|
|
|
private:
|
|
|
|
std::unique_ptr<Count[]> counters_holder;
|
2021-10-11 19:45:47 +00:00
|
|
|
|
|
|
|
friend class Counters;
|
2021-11-08 13:38:31 +00:00
|
|
|
friend struct CountersIncrement;
|
2021-10-11 15:56:23 +00:00
|
|
|
};
|
|
|
|
|
2018-08-17 18:57:07 +00:00
|
|
|
/// Every single value is fetched atomically, but not all values as a whole.
|
2021-10-11 15:56:23 +00:00
|
|
|
Snapshot getPartiallyAtomicSnapshot() const;
|
2018-03-01 16:52:24 +00:00
|
|
|
|
2018-08-17 18:57:07 +00:00
|
|
|
/// Reset all counters to zero and reset parent.
|
2018-02-01 17:55:08 +00:00
|
|
|
void reset();
|
|
|
|
|
2018-05-31 15:54:08 +00:00
|
|
|
/// Get parent (thread unsafe)
|
|
|
|
Counters * getParent()
|
|
|
|
{
|
|
|
|
return parent;
|
|
|
|
}
|
|
|
|
|
2018-05-29 18:14:31 +00:00
|
|
|
/// Set parent (thread unsafe)
|
|
|
|
void setParent(Counters * parent_)
|
|
|
|
{
|
|
|
|
parent = parent_;
|
|
|
|
}
|
|
|
|
|
2018-06-04 14:16:27 +00:00
|
|
|
/// Set all counters to zero
|
2018-02-01 17:55:08 +00:00
|
|
|
void resetCounters();
|
|
|
|
|
|
|
|
static const Event num_counters;
|
|
|
|
};
|
2014-01-03 08:20:13 +00:00
|
|
|
|
2016-10-24 02:02:37 +00:00
|
|
|
/// Increment a counter for event. Thread-safe.
|
2018-02-01 17:55:08 +00:00
|
|
|
void increment(Event event, Count amount = 1);
|
|
|
|
|
2018-09-01 19:51:38 +00:00
|
|
|
/// Get name of event by identifier. Returns statically allocated string.
|
|
|
|
const char * getName(Event event);
|
2014-01-03 08:20:13 +00:00
|
|
|
|
2018-09-01 23:14:48 +00:00
|
|
|
/// Get description of event by identifier. Returns statically allocated string.
|
|
|
|
const char * getDocumentation(Event event);
|
|
|
|
|
2016-10-24 02:02:37 +00:00
|
|
|
/// Get index just after last event identifier.
|
|
|
|
Event end();
|
2021-11-08 13:38:31 +00:00
|
|
|
|
|
|
|
struct CountersIncrement
|
|
|
|
{
|
2021-11-08 20:47:57 +00:00
|
|
|
CountersIncrement() noexcept = default;
|
2021-11-08 13:38:31 +00:00
|
|
|
explicit CountersIncrement(Counters::Snapshot const & snapshot);
|
|
|
|
CountersIncrement(Counters::Snapshot const & after, Counters::Snapshot const & before);
|
|
|
|
|
|
|
|
CountersIncrement(CountersIncrement &&) = default;
|
|
|
|
CountersIncrement & operator=(CountersIncrement &&) = default;
|
|
|
|
|
|
|
|
Increment operator[](Event event) const noexcept
|
|
|
|
{
|
|
|
|
return increment_holder[event];
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
void init();
|
|
|
|
|
|
|
|
static_assert(sizeof(Count) == sizeof(Increment), "Sizes of counter and increment differ");
|
|
|
|
|
|
|
|
std::unique_ptr<Increment[]> increment_holder;
|
|
|
|
};
|
2016-10-24 02:02:37 +00:00
|
|
|
}
|