1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab ft=cpp
#pragma once
#include "common/perf_counters.h"
#include "common/ceph_context.h"
#include "common/config.h"
#include "rgw_dmclock.h"
namespace queue_counters {
enum {
l_first = 427150,
l_qlen,
l_cost,
l_res,
l_res_cost,
l_prio,
l_prio_cost,
l_limit,
l_limit_cost,
l_cancel,
l_cancel_cost,
l_res_latency,
l_prio_latency,
l_last,
};
PerfCountersRef build(CephContext *cct, const std::string& name);
} // namespace queue_counters
namespace throttle_counters {
enum {
l_first = 437219,
l_throttle,
l_outstanding,
l_last
};
PerfCountersRef build(CephContext *cct, const std::string& name);
} // namespace throttle
namespace rgw::dmclock {
// the last client counter would be for global scheduler stats
static constexpr auto counter_size = static_cast<size_t>(client_id::count) + 1;
/// array of per-client counters to serve as GetClientCounters
class ClientCounters {
std::array<PerfCountersRef, counter_size> clients;
public:
ClientCounters(CephContext *cct);
PerfCounters* operator()(client_id client) const {
return clients[static_cast<size_t>(client)].get();
}
};
class ThrottleCounters {
PerfCountersRef counters;
public:
ThrottleCounters(CephContext* const cct,const std::string& name):
counters(throttle_counters::build(cct, name)) {}
PerfCounters* operator()() const {
return counters.get();
}
};
struct ClientSum {
uint64_t count{0};
Cost cost{0};
};
constexpr auto client_count = static_cast<size_t>(client_id::count);
using ClientSums = std::array<ClientSum, client_count>;
void inc(ClientSums& sums, client_id client, Cost cost);
void on_cancel(PerfCounters *c, const ClientSum& sum);
void on_process(PerfCounters* c, const ClientSum& rsum, const ClientSum& psum);
class ClientConfig : public md_config_obs_t {
std::vector<ClientInfo> clients;
void update(const ConfigProxy &conf);
public:
ClientConfig(CephContext *cct);
ClientInfo* operator()(client_id client);
const char** get_tracked_conf_keys() const override;
void handle_conf_change(const ConfigProxy& conf,
const std::set<std::string>& changed) override;
};
class SchedulerCtx {
public:
SchedulerCtx(CephContext* const cct) : sched_t(get_scheduler_t(cct))
{
if(sched_t == scheduler_t::dmclock) {
dmc_client_config = std::make_shared<ClientConfig>(cct);
// we don't have a move only cref std::function yet
dmc_client_counters = std::make_optional<ClientCounters>(cct);
}
}
// We need to construct a std::function from a NonCopyable object
ClientCounters& get_dmc_client_counters() { return dmc_client_counters.value(); }
ClientConfig* const get_dmc_client_config() const { return dmc_client_config.get(); }
private:
scheduler_t sched_t;
std::shared_ptr<ClientConfig> dmc_client_config {nullptr};
std::optional<ClientCounters> dmc_client_counters {std::nullopt};
};
} // namespace rgw::dmclock
|