]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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. | |
11fdf7f2 TL |
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. | |
7c673cae FG |
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 { | |
11fdf7f2 TL |
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 | } | |
7c673cae FG |
43 | } |
44 | ||
45 | ||
46 | int main(int argc, char* argv[]) { | |
11fdf7f2 TL |
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); | |
7c673cae | 65 | } |
11fdf7f2 TL |
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 | ||
9f95a23c TL |
80 | const unsigned server_groups = g_conf.server_groups; |
81 | const unsigned client_groups = g_conf.client_groups; | |
11fdf7f2 TL |
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; | |
9f95a23c TL |
85 | unsigned server_total_count = 0; |
86 | unsigned client_total_count = 0; | |
11fdf7f2 | 87 | |
9f95a23c | 88 | for (unsigned i = 0; i < client_groups; ++i) { |
11fdf7f2 TL |
89 | client_total_count += cli_group[i].client_count; |
90 | } | |
91 | ||
9f95a23c | 92 | for (unsigned i = 0; i < server_groups; ++i) { |
11fdf7f2 TL |
93 | server_total_count += srv_group[i].server_count; |
94 | } | |
95 | ||
96 | std::vector<test::dmc::ClientInfo> client_info; | |
9f95a23c | 97 | for (unsigned i = 0; i < client_groups; ++i) { |
11fdf7f2 TL |
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 | ||
9f95a23c TL |
104 | auto ret_client_group_f = [&](const ClientId& c) -> unsigned { |
105 | unsigned group_max = 0; | |
106 | unsigned i = 0; | |
11fdf7f2 TL |
107 | for (; i < client_groups; ++i) { |
108 | group_max += cli_group[i].client_count; | |
109 | if (c < group_max) { | |
110 | break; | |
7c673cae | 111 | } |
7c673cae | 112 | } |
11fdf7f2 TL |
113 | return i; |
114 | }; | |
115 | ||
9f95a23c TL |
116 | auto ret_server_group_f = [&](const ServerId& s) -> unsigned { |
117 | unsigned group_max = 0; | |
118 | unsigned i = 0; | |
11fdf7f2 TL |
119 | for (; i < server_groups; ++i) { |
120 | group_max += srv_group[i].server_count; | |
121 | if (s < group_max) { | |
122 | break; | |
123 | } | |
7c673cae | 124 | } |
11fdf7f2 TL |
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; | |
9f95a23c | 159 | for (unsigned i = 0; i < client_groups; ++i) { |
11fdf7f2 TL |
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 } } ); | |
7c673cae | 173 | } |
11fdf7f2 TL |
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* { | |
9f95a23c | 202 | unsigned i = ret_server_group_f(id); |
11fdf7f2 TL |
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* { | |
9f95a23c | 212 | unsigned i = ret_client_group_f(id); |
11fdf7f2 | 213 | test::MySim::ClientBasedServerSelectFunc server_select_f; |
9f95a23c | 214 | unsigned client_server_select_range = cli_group[i].client_server_select_range; |
11fdf7f2 TL |
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); | |
7c673cae | 219 | } |
11fdf7f2 TL |
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 | }; | |
7c673cae FG |
226 | |
227 | #if 1 | |
11fdf7f2 | 228 | std::cout << "[global]" << std::endl << g_conf << std::endl; |
9f95a23c | 229 | for (unsigned i = 0; i < client_groups; ++i) { |
11fdf7f2 TL |
230 | std::cout << std::endl << "[client." << i << "]" << std::endl; |
231 | std::cout << cli_group[i] << std::endl; | |
232 | } | |
9f95a23c | 233 | for (unsigned i = 0; i < server_groups; ++i) { |
11fdf7f2 TL |
234 | std::cout << std::endl << "[server." << i << "]" << std::endl; |
235 | std::cout << srv_group[i] << std::endl; | |
236 | } | |
237 | std::cout << std::endl; | |
7c673cae FG |
238 | #endif |
239 | ||
11fdf7f2 TL |
240 | simulation->add_servers(server_total_count, create_server_f); |
241 | simulation->add_clients(client_total_count, create_client_f); | |
7c673cae | 242 | |
11fdf7f2 TL |
243 | simulation->run(); |
244 | simulation->display_stats(std::cout, | |
245 | &test::server_data, &test::client_data, | |
246 | server_disp_filter, client_disp_filter); | |
31f18b77 | 247 | |
11fdf7f2 | 248 | delete simulation; |
7c673cae FG |
249 | } // main |
250 | ||
251 | ||
252 | void test::client_data(std::ostream& out, | |
11fdf7f2 TL |
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:"; | |
9f95a23c | 261 | for (unsigned i = 0; i < sim->get_client_count(); ++i) { |
11fdf7f2 TL |
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:"; | |
9f95a23c | 273 | for (unsigned i = 0; i < sim->get_client_count(); ++i) { |
11fdf7f2 TL |
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; | |
7c673cae FG |
282 | } |
283 | ||
284 | ||
285 | void test::server_data(std::ostream& out, | |
11fdf7f2 TL |
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; | |
9f95a23c | 291 | for (unsigned i = 0; i < sim->get_server_count(); ++i) { |
11fdf7f2 TL |
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; | |
9f95a23c | 303 | for (unsigned i = 0; i < sim->get_server_count(); ++i) { |
11fdf7f2 TL |
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; | |
7c673cae FG |
317 | |
318 | #ifdef PROFILE | |
11fdf7f2 TL |
319 | crimson::ProfileCombiner<std::chrono::nanoseconds> art_combiner; |
320 | crimson::ProfileCombiner<std::chrono::nanoseconds> rct_combiner; | |
9f95a23c | 321 | for (unsigned i = 0; i < sim->get_server_count(); ++i) { |
11fdf7f2 TL |
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; | |
7c673cae FG |
341 | #endif |
342 | } |