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