1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
5 * Copyright (C) 2016 Red Hat Inc.
9 #include "test_dmclock.h"
17 namespace dmc
= crimson::dmclock
;
18 namespace test
= crimson::test_dmc
;
19 namespace sim
= crimson::qos_simulation
;
21 using namespace std::placeholders
;
26 void server_data(std::ostream
& out
,
28 test::MySim::ServerFilter server_disp_filter
,
29 int head_w
, int data_w
, int data_prec
);
31 void client_data(std::ostream
& out
,
33 test::MySim::ClientFilter client_disp_filter
,
34 int head_w
, int data_w
, int data_prec
);
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
]);
45 std::string conf_file_list
;
46 sim::ceph_argparse_early_args(args
, &conf_file_list
);
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
;
52 if (!conf_file_list
.empty()) {
54 ret
= sim::parse_config_file(conf_file_list
, g_conf
);
60 // default simulation parameter
61 g_conf
.client_groups
= 2;
64 srv_group
.push_back(st
);
66 sim::cli_group_t
ct1(99, 0);
67 cli_group
.push_back(ct1
);
69 sim::cli_group_t
ct2(1, 10);
70 cli_group
.push_back(ct2
);
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;
80 for (uint i
= 0; i
< client_groups
; ++i
) {
81 client_total_count
+= cli_group
[i
].client_count
;
84 for (uint i
= 0; i
< server_groups
; ++i
) {
85 server_total_count
+= srv_group
[i
].server_count
;
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
} );
96 auto ret_client_group_f
= [&](const ClientId
& c
) -> uint
{
99 for (; i
< client_groups
; ++i
) {
100 group_max
+= cli_group
[i
].client_count
;
108 auto ret_server_group_f
= [&](const ServerId
& s
) -> uint
{
111 for (; i
< server_groups
; ++i
) {
112 group_max
+= srv_group
[i
].server_count
;
120 auto client_info_f
= [=](const ClientId
& c
) -> test::dmc::ClientInfo
{
121 return client_info
[ret_client_group_f(c
)];
124 auto client_disp_filter
= [=] (const ClientId
& i
) -> bool {
125 return i
< 3 || i
>= (client_total_count
- 3);
128 auto server_disp_filter
= [=] (const ServerId
& i
) -> bool {
129 return i
< 3 || i
>= (server_total_count
- 3);
133 test::MySim
*simulation
;
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 const 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(request
, client_id
, req_params
);
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)) {
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
} } );
156 { { sim::wait_op
, cli_group
[i
].client_wait
},
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
} } );
164 simulation
= new test::MySim();
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
,
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
);
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
,
189 test::dmc_server_accumulate_f
,
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
);
200 server_select_f
= simulation
->make_server_select_ran_range(client_server_select_range
);
202 return new test::DmcClient(id
,
204 std::bind(server_select_f
, _1
, id
),
205 test::dmc_client_accumulate_f
,
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
;
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
;
219 std::cout
<< std::endl
;
222 simulation
->add_servers(server_total_count
, create_server_f
);
223 simulation
->add_clients(client_total_count
, create_client_f
);
226 simulation
->display_stats(std::cout
,
227 &test::server_data
, &test::client_data
,
228 server_disp_filter
, client_disp_filter
);
234 void test::client_data(std::ostream
& out
,
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
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
;
247 if (!client_disp_filter(i
)) continue;
248 out
<< " " << std::setw(data_w
) << r
;
250 out
<< " " << std::setw(data_w
) << std::setprecision(data_prec
) <<
251 std::fixed
<< total_r
<< std::endl
;
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
;
259 if (!client_disp_filter(i
)) continue;
260 out
<< " " << std::setw(data_w
) << p
;
262 out
<< " " << std::setw(data_w
) << std::setprecision(data_prec
) <<
263 std::fixed
<< total_p
<< std::endl
;
267 void test::server_data(std::ostream
& out
,
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:";
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
;
277 if (!server_disp_filter(i
)) continue;
278 out
<< " " << std::setw(data_w
) << rc
;
280 out
<< " " << std::setw(data_w
) << std::setprecision(data_prec
) <<
281 std::fixed
<< total_r
<< std::endl
;
283 out
<< std::setw(head_w
) << "prop_ops:";
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
;
289 if (!server_disp_filter(i
)) continue;
290 out
<< " " << std::setw(data_w
) << pc
;
292 out
<< " " << std::setw(data_w
) << std::setprecision(data_prec
) <<
293 std::fixed
<< total_p
<< std::endl
;
295 const auto& q
= sim
->get_server(0).get_priority_queue();
297 " k-way heap: " << q
.get_heap_branching_factor() << std::endl
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
);
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()) <<