Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / 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 }