]> git.proxmox.com Git - ceph.git/blob - ceph/src/dmclock/sim/src/test_dmclock_main.cc
update sources to v12.1.3
[ceph.git] / ceph / src / dmclock / sim / src / test_dmclock_main.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 /*
5 * Copyright (C) 2016 Red Hat Inc.
6 */
7
8
9 #include "test_dmclock.h"
10 #include "config.h"
11
12 #ifdef PROFILE
13 #include "profile.h"
14 #endif
15
16
17 namespace dmc = crimson::dmclock;
18 namespace test = crimson::test_dmc;
19 namespace sim = crimson::qos_simulation;
20
21 using namespace std::placeholders;
22
23
24 namespace crimson {
25 namespace test_dmc {
26 void server_data(std::ostream& out,
27 test::MySim* sim,
28 test::MySim::ServerFilter server_disp_filter,
29 int head_w, int data_w, int data_prec);
30
31 void client_data(std::ostream& out,
32 test::MySim* sim,
33 test::MySim::ClientFilter client_disp_filter,
34 int head_w, int data_w, int data_prec);
35 }
36 }
37
38
39 int main(int argc, char* argv[]) {
40 std::vector<const char*> args;
41 for (int i = 1; i < argc; ++i) {
42 args.push_back(argv[i]);
43 }
44
45 std::string conf_file_list;
46 sim::ceph_argparse_early_args(args, &conf_file_list);
47
48 sim::sim_config_t g_conf;
49 std::vector<sim::cli_group_t> &cli_group = g_conf.cli_group;
50 std::vector<sim::srv_group_t> &srv_group = g_conf.srv_group;
51
52 if (!conf_file_list.empty()) {
53 int ret;
54 ret = sim::parse_config_file(conf_file_list, g_conf);
55 if (ret) {
56 // error
57 _exit(1);
58 }
59 } else {
60 // default simulation parameter
61 g_conf.client_groups = 2;
62
63 sim::srv_group_t st;
64 srv_group.push_back(st);
65
66 sim::cli_group_t ct1(99, 0);
67 cli_group.push_back(ct1);
68
69 sim::cli_group_t ct2(1, 10);
70 cli_group.push_back(ct2);
71 }
72
73 const uint server_groups = g_conf.server_groups;
74 const uint client_groups = g_conf.client_groups;
75 const bool server_random_selection = g_conf.server_random_selection;
76 const bool server_soft_limit = g_conf.server_soft_limit;
77 uint server_total_count = 0;
78 uint client_total_count = 0;
79
80 for (uint i = 0; i < client_groups; ++i) {
81 client_total_count += cli_group[i].client_count;
82 }
83
84 for (uint i = 0; i < server_groups; ++i) {
85 server_total_count += srv_group[i].server_count;
86 }
87
88 std::vector<test::dmc::ClientInfo> client_info;
89 for (uint i = 0; i < client_groups; ++i) {
90 client_info.push_back(test::dmc::ClientInfo
91 { cli_group[i].client_reservation,
92 cli_group[i].client_weight,
93 cli_group[i].client_limit } );
94 }
95
96 auto ret_client_group_f = [&](const ClientId& c) -> uint {
97 uint group_max = 0;
98 uint i = 0;
99 for (; i < client_groups; ++i) {
100 group_max += cli_group[i].client_count;
101 if (c < group_max) {
102 break;
103 }
104 }
105 return i;
106 };
107
108 auto ret_server_group_f = [&](const ServerId& s) -> uint {
109 uint group_max = 0;
110 uint i = 0;
111 for (; i < server_groups; ++i) {
112 group_max += srv_group[i].server_count;
113 if (s < group_max) {
114 break;
115 }
116 }
117 return i;
118 };
119
120 auto client_info_f = [=](const ClientId& c) -> test::dmc::ClientInfo {
121 return client_info[ret_client_group_f(c)];
122 };
123
124 auto client_disp_filter = [=] (const ClientId& i) -> bool {
125 return i < 3 || i >= (client_total_count - 3);
126 };
127
128 auto server_disp_filter = [=] (const ServerId& i) -> bool {
129 return i < 3 || i >= (server_total_count - 3);
130 };
131
132
133 test::MySim *simulation;
134
135
136 // lambda to post a request to the identified server; called by client
137 test::SubmitFunc server_post_f =
138 [&simulation](const ServerId& server,
139 sim::TestRequest&& request,
140 const ClientId& client_id,
141 const test::dmc::ReqParams& req_params) {
142 test::DmcServer& s = simulation->get_server(server);
143 s.post(std::move(request), client_id, req_params);
144 };
145
146 std::vector<std::vector<sim::CliInst>> cli_inst;
147 for (uint i = 0; i < client_groups; ++i) {
148 if (cli_group[i].client_wait == std::chrono::seconds(0)) {
149 cli_inst.push_back(
150 { { sim::req_op,
151 (uint32_t)cli_group[i].client_total_ops,
152 (double)cli_group[i].client_iops_goal,
153 (uint16_t)cli_group[i].client_outstanding_ops } } );
154 } else {
155 cli_inst.push_back(
156 { { sim::wait_op, cli_group[i].client_wait },
157 { sim::req_op,
158 (uint32_t)cli_group[i].client_total_ops,
159 (double)cli_group[i].client_iops_goal,
160 (uint16_t)cli_group[i].client_outstanding_ops } } );
161 }
162 }
163
164 simulation = new test::MySim();
165
166 test::DmcServer::ClientRespFunc client_response_f =
167 [&simulation](ClientId client_id,
168 const sim::TestResponse& resp,
169 const ServerId& server_id,
170 const dmc::PhaseType& phase) {
171 simulation->get_client(client_id).receive_response(resp,
172 server_id,
173 phase);
174 };
175
176 test::CreateQueueF create_queue_f =
177 [&](test::DmcQueue::CanHandleRequestFunc can_f,
178 test::DmcQueue::HandleRequestFunc handle_f) -> test::DmcQueue* {
179 return new test::DmcQueue(client_info_f, can_f, handle_f, server_soft_limit);
180 };
181
182
183 auto create_server_f = [&](ServerId id) -> test::DmcServer* {
184 uint i = ret_server_group_f(id);
185 return new test::DmcServer(id,
186 srv_group[i].server_iops,
187 srv_group[i].server_threads,
188 client_response_f,
189 test::dmc_server_accumulate_f,
190 create_queue_f);
191 };
192
193 auto create_client_f = [&](ClientId id) -> test::DmcClient* {
194 uint i = ret_client_group_f(id);
195 test::MySim::ClientBasedServerSelectFunc server_select_f;
196 uint client_server_select_range = cli_group[i].client_server_select_range;
197 if (!server_random_selection) {
198 server_select_f = simulation->make_server_select_alt_range(client_server_select_range);
199 } else {
200 server_select_f = simulation->make_server_select_ran_range(client_server_select_range);
201 }
202 return new test::DmcClient(id,
203 server_post_f,
204 std::bind(server_select_f, _1, id),
205 test::dmc_client_accumulate_f,
206 cli_inst[i]);
207 };
208
209 #if 1
210 std::cout << "[global]" << std::endl << g_conf << std::endl;
211 for (uint i = 0; i < client_groups; ++i) {
212 std::cout << std::endl << "[client." << i << "]" << std::endl;
213 std::cout << cli_group[i] << std::endl;
214 }
215 for (uint i = 0; i < server_groups; ++i) {
216 std::cout << std::endl << "[server." << i << "]" << std::endl;
217 std::cout << srv_group[i] << std::endl;
218 }
219 std::cout << std::endl;
220 #endif
221
222 simulation->add_servers(server_total_count, create_server_f);
223 simulation->add_clients(client_total_count, create_client_f);
224
225 simulation->run();
226 simulation->display_stats(std::cout,
227 &test::server_data, &test::client_data,
228 server_disp_filter, client_disp_filter);
229
230 delete simulation;
231 } // main
232
233
234 void test::client_data(std::ostream& out,
235 test::MySim* sim,
236 test::MySim::ClientFilter client_disp_filter,
237 int head_w, int data_w, int data_prec) {
238 // report how many ops were done by reservation and proportion for
239 // each client
240
241 int total_r = 0;
242 out << std::setw(head_w) << "res_ops:";
243 for (uint i = 0; i < sim->get_client_count(); ++i) {
244 const auto& client = sim->get_client(i);
245 auto r = client.get_accumulator().reservation_count;
246 total_r += r;
247 if (!client_disp_filter(i)) continue;
248 out << " " << std::setw(data_w) << r;
249 }
250 out << " " << std::setw(data_w) << std::setprecision(data_prec) <<
251 std::fixed << total_r << std::endl;
252
253 int total_p = 0;
254 out << std::setw(head_w) << "prop_ops:";
255 for (uint i = 0; i < sim->get_client_count(); ++i) {
256 const auto& client = sim->get_client(i);
257 auto p = client.get_accumulator().proportion_count;
258 total_p += p;
259 if (!client_disp_filter(i)) continue;
260 out << " " << std::setw(data_w) << p;
261 }
262 out << " " << std::setw(data_w) << std::setprecision(data_prec) <<
263 std::fixed << total_p << std::endl;
264 }
265
266
267 void test::server_data(std::ostream& out,
268 test::MySim* sim,
269 test::MySim::ServerFilter server_disp_filter,
270 int head_w, int data_w, int data_prec) {
271 out << std::setw(head_w) << "res_ops:";
272 int total_r = 0;
273 for (uint i = 0; i < sim->get_server_count(); ++i) {
274 const auto& server = sim->get_server(i);
275 auto rc = server.get_accumulator().reservation_count;
276 total_r += rc;
277 if (!server_disp_filter(i)) continue;
278 out << " " << std::setw(data_w) << rc;
279 }
280 out << " " << std::setw(data_w) << std::setprecision(data_prec) <<
281 std::fixed << total_r << std::endl;
282
283 out << std::setw(head_w) << "prop_ops:";
284 int total_p = 0;
285 for (uint i = 0; i < sim->get_server_count(); ++i) {
286 const auto& server = sim->get_server(i);
287 auto pc = server.get_accumulator().proportion_count;
288 total_p += pc;
289 if (!server_disp_filter(i)) continue;
290 out << " " << std::setw(data_w) << pc;
291 }
292 out << " " << std::setw(data_w) << std::setprecision(data_prec) <<
293 std::fixed << total_p << std::endl;
294
295 const auto& q = sim->get_server(0).get_priority_queue();
296 out << std::endl <<
297 " k-way heap: " << q.get_heap_branching_factor() << std::endl
298 << std::endl;
299
300 #ifdef PROFILE
301 crimson::ProfileCombiner<std::chrono::nanoseconds> art_combiner;
302 crimson::ProfileCombiner<std::chrono::nanoseconds> rct_combiner;
303 for (uint i = 0; i < sim->get_server_count(); ++i) {
304 const auto& q = sim->get_server(i).get_priority_queue();
305 const auto& art = q.add_request_timer;
306 art_combiner.combine(art);
307 const auto& rct = q.request_complete_timer;
308 rct_combiner.combine(rct);
309 }
310 out << "Server add_request_timer: count:" << art_combiner.get_count() <<
311 ", mean:" << art_combiner.get_mean() <<
312 ", std_dev:" << art_combiner.get_std_dev() <<
313 ", low:" << art_combiner.get_low() <<
314 ", high:" << art_combiner.get_high() << std::endl;
315 out << "Server request_complete_timer: count:" << rct_combiner.get_count() <<
316 ", mean:" << rct_combiner.get_mean() <<
317 ", std_dev:" << rct_combiner.get_std_dev() <<
318 ", low:" << rct_combiner.get_low() <<
319 ", high:" << rct_combiner.get_high() << std::endl;
320 out << "Server combined mean: " <<
321 (art_combiner.get_mean() + rct_combiner.get_mean()) <<
322 std::endl;
323 #endif
324 }