userver
C++ Async Framework
Toggle main menu visibility
Loading...
Searching...
No Matches
striped_rate_counter.hpp
Go to the documentation of this file.
1
#
pragma
once
2
3
/// @file userver/utils/statistics/striped_rate_counter.hpp
4
/// @brief @copybrief utils::statistics::StripedRateCounter
5
6
#
include
<
atomic
>
7
#
include
<
cstdint
>
8
9
#
include
<
userver
/
concurrent
/
striped_counter
.
hpp
>
10
#
include
<
userver
/
utils
/
statistics
/
fwd
.
hpp
>
11
#
include
<
userver
/
utils
/
statistics
/
rate
.
hpp
>
12
13
USERVER_NAMESPACE_BEGIN
14
15
namespace
utils
::
statistics
{
16
17
/// @brief Atomic counter of type Rate with relaxed memory ordering, increased
18
/// memory consumption and decreased contention.
19
///
20
/// This class is represented as Rate metric when serializing to statistics.
21
///
22
/// Differences from utils::statistics::RateCounter:
23
//
24
/// 1. StripedRateCounter takes `8 * N_CORES` memory, while RateCounter is just
25
/// a single atomic.
26
/// 2. StripedRateCounter uses split counters on x86_64, which results
27
/// in perfect performance even under heavy concurrent usage.
28
///
29
/// Use StripedRateCounter instead of RateCounter sparingly, in places where a
30
/// lot of threads are supposed to be hammering on the same metrics.
31
class
StripedRateCounter
final
{
32
public
:
33
using
ValueType =
Rate
;
34
35
StripedRateCounter() =
default
;
36
37
explicit
StripedRateCounter(
Rate
desired) { Add(desired); }
38
39
explicit
StripedRateCounter(
Rate
::ValueType desired)
40
: StripedRateCounter(
Rate
{desired})
41
{}
42
43
StripedRateCounter(
const
StripedRateCounter& other) { val_
.
Add
(
other.LoadImpl()
)
; }
44
45
StripedRateCounter& operator=(
const
StripedRateCounter& other)
noexcept
{
46
if
(
this
== &other) {
47
return
*
this
;
48
}
49
50
offset_ = other.LoadImpl() - val_
.
Read
(
)
;
51
return
*
this
;
52
}
53
54
StripedRateCounter& operator=(
Rate
desired)
noexcept
{
55
Store(desired);
56
return
*
this
;
57
}
58
59
void
Store(
Rate
desired)
noexcept
{ offset_ =
static_cast
<std::uintptr_t>(desired.value) - val_
.
Read
(
)
; }
60
61
Rate
Load()
const
noexcept
{
return
Rate
{
static_cast
<std::uint64_t>(LoadImpl())}; }
62
63
void
Add(
Rate
arg)
noexcept
{ val_
.
Add
(
static_cast
<std::uintptr_t>(arg.value)
)
; }
64
65
StripedRateCounter& operator++()
noexcept
{
66
val_
.
Add
(
1
)
;
67
return
*
this
;
68
}
69
70
StripedRateCounter& operator+=(
Rate
arg)
noexcept
{
71
Add(arg);
72
return
*
this
;
73
}
74
75
StripedRateCounter& operator+=(
const
StripedRateCounter& arg)
noexcept
{
76
val_
.
Add
(
arg.LoadImpl()
)
;
77
return
*
this
;
78
}
79
80
private
:
81
// Implementation note: any operation that assigns a value (instead of adding)
82
// would induce race condition if implemented using LoadImpl(). Use offset_
83
// directly instead for those.
84
std::uintptr_t LoadImpl()
const
noexcept
{
return
val_
.
Read
(
)
+ offset_.load(std::memory_order_relaxed); }
85
86
USERVER_NAMESPACE::
concurrent
::StripedCounter val_;
87
std::atomic<std::uintptr_t> offset_{0};
88
};
89
90
void
DumpMetric(Writer& writer,
const
StripedRateCounter& value);
91
92
void
ResetMetric(StripedRateCounter& value);
93
94
}
// namespace utils::statistics
95
96
USERVER_NAMESPACE_END
userver
utils
statistics
striped_rate_counter.hpp
Generated on
for userver by
Doxygen
1.17.0