]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // |
2 | // tcp_client.cpp | |
3 | // ~~~~~~~~~~~~~~ | |
4 | // | |
b32b8144 | 5 | // Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) |
7c673cae FG |
6 | // |
7 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
8 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
9 | // | |
10 | ||
11 | #include <boost/asio/ip/tcp.hpp> | |
12 | #include <boost/asio/read.hpp> | |
13 | #include <boost/asio/write.hpp> | |
14 | #include <boost/date_time/posix_time/posix_time_types.hpp> | |
15 | #include <boost/shared_ptr.hpp> | |
16 | #include <cstdio> | |
17 | #include <cstdlib> | |
18 | #include <cstring> | |
19 | #include <vector> | |
20 | #include "high_res_clock.hpp" | |
21 | ||
22 | using boost::asio::ip::tcp; | |
23 | using boost::posix_time::ptime; | |
24 | using boost::posix_time::microsec_clock; | |
25 | ||
26 | const int num_samples = 100000; | |
27 | ||
28 | struct transfer_all | |
29 | { | |
30 | typedef std::size_t result_type; | |
31 | std::size_t operator()(const boost::system::error_code& ec, std::size_t) | |
32 | { | |
33 | return (ec && ec != boost::asio::error::would_block) ? 0 : ~0; | |
34 | } | |
35 | }; | |
36 | ||
37 | int main(int argc, char* argv[]) | |
38 | { | |
39 | if (argc != 6) | |
40 | { | |
41 | std::fprintf(stderr, | |
42 | "Usage: tcp_client <ip> <port> " | |
43 | "<nconns> <bufsize> {spin|block}\n"); | |
44 | return 1; | |
45 | } | |
46 | ||
47 | const char* ip = argv[1]; | |
48 | unsigned short port = static_cast<unsigned short>(std::atoi(argv[2])); | |
49 | int num_connections = std::atoi(argv[3]); | |
50 | std::size_t buf_size = static_cast<std::size_t>(std::atoi(argv[4])); | |
51 | bool spin = (std::strcmp(argv[5], "spin") == 0); | |
52 | ||
b32b8144 | 53 | boost::asio::io_context io_context; |
7c673cae FG |
54 | std::vector<boost::shared_ptr<tcp::socket> > sockets; |
55 | ||
56 | for (int i = 0; i < num_connections; ++i) | |
57 | { | |
b32b8144 | 58 | boost::shared_ptr<tcp::socket> s(new tcp::socket(io_context)); |
7c673cae | 59 | |
b32b8144 | 60 | tcp::endpoint target(boost::asio::ip::make_address(ip), port); |
7c673cae FG |
61 | s->connect(target); |
62 | ||
63 | s->set_option(tcp::no_delay(true)); | |
64 | ||
65 | if (spin) | |
66 | { | |
b32b8144 | 67 | s->non_blocking(true); |
7c673cae FG |
68 | } |
69 | ||
70 | sockets.push_back(s); | |
71 | } | |
72 | ||
73 | std::vector<unsigned char> write_buf(buf_size); | |
74 | std::vector<unsigned char> read_buf(buf_size); | |
75 | ||
76 | ptime start = microsec_clock::universal_time(); | |
77 | boost::uint64_t start_hr = high_res_clock(); | |
78 | ||
79 | boost::uint64_t samples[num_samples]; | |
80 | for (int i = 0; i < num_samples; ++i) | |
81 | { | |
82 | tcp::socket& socket = *sockets[i % num_connections]; | |
83 | ||
84 | boost::uint64_t t = high_res_clock(); | |
85 | ||
86 | boost::system::error_code ec; | |
87 | boost::asio::write(socket, | |
88 | boost::asio::buffer(write_buf), | |
89 | transfer_all(), ec); | |
90 | ||
91 | boost::asio::read(socket, | |
92 | boost::asio::buffer(read_buf), | |
93 | transfer_all(), ec); | |
94 | ||
95 | samples[i] = high_res_clock() - t; | |
96 | } | |
97 | ||
98 | ptime stop = microsec_clock::universal_time(); | |
99 | boost::uint64_t stop_hr = high_res_clock(); | |
100 | boost::uint64_t elapsed_usec = (stop - start).total_microseconds(); | |
101 | boost::uint64_t elapsed_hr = stop_hr - start_hr; | |
102 | double scale = 1.0 * elapsed_usec / elapsed_hr; | |
103 | ||
104 | std::sort(samples, samples + num_samples); | |
105 | std::printf(" 0.0%%\t%f\n", samples[0] * scale); | |
106 | std::printf(" 0.1%%\t%f\n", samples[num_samples / 1000 - 1] * scale); | |
107 | std::printf(" 1.0%%\t%f\n", samples[num_samples / 100 - 1] * scale); | |
108 | std::printf(" 10.0%%\t%f\n", samples[num_samples / 10 - 1] * scale); | |
109 | std::printf(" 20.0%%\t%f\n", samples[num_samples * 2 / 10 - 1] * scale); | |
110 | std::printf(" 30.0%%\t%f\n", samples[num_samples * 3 / 10 - 1] * scale); | |
111 | std::printf(" 40.0%%\t%f\n", samples[num_samples * 4 / 10 - 1] * scale); | |
112 | std::printf(" 50.0%%\t%f\n", samples[num_samples * 5 / 10 - 1] * scale); | |
113 | std::printf(" 60.0%%\t%f\n", samples[num_samples * 6 / 10 - 1] * scale); | |
114 | std::printf(" 70.0%%\t%f\n", samples[num_samples * 7 / 10 - 1] * scale); | |
115 | std::printf(" 80.0%%\t%f\n", samples[num_samples * 8 / 10 - 1] * scale); | |
116 | std::printf(" 90.0%%\t%f\n", samples[num_samples * 9 / 10 - 1] * scale); | |
117 | std::printf(" 99.0%%\t%f\n", samples[num_samples * 99 / 100 - 1] * scale); | |
118 | std::printf(" 99.9%%\t%f\n", samples[num_samples * 999 / 1000 - 1] * scale); | |
119 | std::printf("100.0%%\t%f\n", samples[num_samples - 1] * scale); | |
120 | ||
121 | double total = 0.0; | |
122 | for (int i = 0; i < num_samples; ++i) total += samples[i] * scale; | |
123 | std::printf(" mean\t%f\n", total / num_samples); | |
124 | } |