11#include < fstream>
22#include < iostream>
3- #include < list>
43#include < thread>
54
65#include < boost/program_options.hpp>
76
87#include < userver/clients/http/client.hpp>
98#include < userver/engine/async.hpp>
9+ #include < userver/engine/get_all.hpp>
1010#include < userver/engine/run_standalone.hpp>
1111#include < userver/http/http_version.hpp>
1212#include < userver/logging/log.hpp>
@@ -21,101 +21,88 @@ namespace http = clients::http;
2121struct Config {
2222 std::string log_level = " error" ;
2323 std::string logfile = " " ;
24- size_t count = 1000 ;
25- size_t coroutines = 1 ;
26- size_t worker_threads = 1 ;
27- size_t io_threads = 1 ;
24+ std:: size_t count = 1000 ;
25+ std:: size_t coroutines = 1 ;
26+ std:: size_t worker_threads = 1 ;
27+ std:: size_t io_threads = 1 ;
2828 long timeout_ms = 1000 ;
2929 bool multiplexing = false ;
30- size_t max_host_connections = 0 ;
30+ std:: size_t max_host_connections = 0 ;
3131 USERVER_NAMESPACE ::http::HttpVersion http_version = USERVER_NAMESPACE ::http::HttpVersion::k11;
3232 std::string url_file;
3333};
3434
3535struct WorkerContext {
36- std::atomic<uint64_t > counter{0 };
37- const uint64_t print_each_counter;
38- uint64_t response_len;
36+ std::atomic<std:: uint64_t > counter{0 };
37+ const std:: uint64_t print_each_counter;
38+ std:: uint64_t response_len;
3939
4040 http::Client& http_client;
4141 const Config& config;
4242 const std::vector<std::string>& urls;
4343};
4444
45- Config ParseConfig (int argc, char * argv[]) {
45+ Config ParseConfig (int argc, const char * const argv[]) {
4646 namespace po = boost::program_options;
4747
48- Config config ;
48+ Config c ;
4949 po::options_description desc (" Allowed options" );
50- desc. add_options ()( " help,h " , " produce help message " )(
51- " log-level " ,
52- po::value (&config. log_level )-> default_value (config. log_level ),
53- " log level (trace, debug, info, warning, error) "
54- ) (" log-file " ,
55- po::value (&config .logfile )->default_value (config .logfile ),
56- " log filename (empty for synchronous stderr) " )(
57- " url-file,f " , po::value (&config. url_file )->default_value (config. url_file ), " input file "
58- )( " count,c " , po::value (&config. count )->default_value (config. count ), " request count" )(
59- " coroutines " , po::value (&config. coroutines )->default_value (config. coroutines ), " client coroutine count"
60- )( " worker -threads" , po::value (&config. worker_threads )->default_value (config. worker_threads ), " worker thread count" )(
61- " io-threads " , po::value (&config. io_threads )->default_value (config. io_threads ), " io thread count "
62- )( " timeout,t " , po::value (&config. timeout_ms )-> default_value (config. timeout_ms ), " request timeout in ms " )(
63- " multiplexing " , " enable HTTP/2 multiplexing "
64- )( " http-version,V " , po::value<std::string>(), " http version, possible values: 1.0, 1.1, 2.0-prior "
65- )( " max- host-connections " ,
66- po::value (&config. max_host_connections )-> default_value (config. max_host_connections ),
67- " maximum HTTP connection number to a single host " );
50+
51+ // clang-format off
52+ desc. add_options ()
53+ ( " help,h " , " produce help message " )
54+ (" log-level " , po::value (&c. log_level )-> default_value (c. log_level ), " One of: trace, debug, info, warning, error " )
55+ ( " log-file " , po::value (&c .logfile )->default_value (c .logfile ), " log filename (empty for synchronous stderr) " )
56+ ( " url-file,f " , po::value (&c. url_file )-> default_value (c. url_file ), " input file " )
57+ ( " count,c " , po::value (&c. count )->default_value (c. count ), " request count " )
58+ ( " coroutines " , po::value (&c. coroutines )->default_value (c. coroutines ), " client coroutine count" )
59+ ( " worker-threads " , po::value (&c. worker_threads )->default_value (c. worker_threads ), " worker thread count" )
60+ ( " io -threads" , po::value (&c. io_threads )->default_value (c. io_threads ), " IO thread count" )
61+ ( " timeout,t " , po::value (&c. timeout_ms )->default_value (c. timeout_ms ), " request timeout in ms " )
62+ ( " multiplexing " , " enable HTTP/2 multiplexing " )
63+ ( " http-version,V " , po::value<std::string>(), " http version, possible values: 1.0, 1.1, 2, 2-prior " )
64+ ( " max-host-connections " , po::value (&c. max_host_connections )-> default_value (c. max_host_connections )
65+ , " maximum HTTP connection number to a single host" )
66+ ;
67+ // clang-format on
6868
6969 po::variables_map vm;
7070 po::store (po::parse_command_line (argc, argv, desc), vm);
7171 po::notify (vm);
7272
7373 if (vm.count (" help" )) {
7474 std::cout << desc << std::endl;
75- exit (0 );
75+ std:: exit (0 );
7676 }
7777
78- if ( vm.count (" multiplexing" )) config. multiplexing = true ;
78+ c. multiplexing = vm.count (" multiplexing" );
7979 if (vm.count (" http-version" )) {
80- auto value = vm[" http-version" ].as <std::string>();
81- if (value == " 1.0" )
82- config.http_version = USERVER_NAMESPACE ::http::HttpVersion::k10;
83- else if (value == " 1.1" )
84- config.http_version = USERVER_NAMESPACE ::http::HttpVersion::k11;
85- else if (value == " 2" )
86- config.http_version = USERVER_NAMESPACE ::http::HttpVersion::k2;
87- else if (value == " 2tls" )
88- config.http_version = USERVER_NAMESPACE ::http::HttpVersion::k2Tls;
89- else if (value == " 2-prior" )
90- config.http_version = USERVER_NAMESPACE ::http::HttpVersion::k2PriorKnowledge;
91- else {
92- std::cerr << " --http-version value is unknown" << std::endl;
93- exit (1 );
94- }
80+ c.http_version = USERVER_NAMESPACE::http::HttpVersionFromString (vm[" http-version" ].as <std::string>());
9581 }
9682
97- if (config .url_file .empty ()) {
83+ if (c .url_file .empty ()) {
9884 std::cerr << " url-file is undefined" << std::endl;
9985 std::cout << desc << std::endl;
100- exit (1 );
86+ std:: exit (1 );
10187 }
10288
103- return config ;
89+ return c ;
10490}
10591
10692std::vector<std::string> ReadUrls (const Config& config) {
10793 std::vector<std::string> urls;
10894
10995 std::ifstream infile (config.url_file );
11096 if (!infile.is_open ()) {
111- std::cerr << " failed to open url-file\n " ;
112- exit (1 );
97+ throw std::runtime_error (" Failed to open url-file\n " );
11398 }
11499
115100 std::string line;
116101 while (std::getline (infile, line)) urls.emplace_back (std::move (line));
117102
118- if (urls.empty ()) throw std::runtime_error (" No URL in URL file!" );
103+ if (urls.empty ()) {
104+ throw std::runtime_error (" No URL in URL file!" );
105+ }
119106
120107 return urls;
121108}
@@ -139,15 +126,15 @@ void Worker(WorkerContext& context) {
139126 const std::string& url = context.urls [idx % context.urls .size ()];
140127
141128 try {
142- auto ts1 = std::chrono::system_clock::now ();
129+ const auto ts1 = std::chrono::system_clock::now ();
143130 auto request = CreateRequest (context.http_client , context.config , url);
144- auto ts2 = std::chrono::system_clock::now ();
131+ const auto ts2 = std::chrono::system_clock::now ();
145132 LOG_DEBUG () << " CreateRequest" ;
146133
147134 auto response = request.perform ();
148135 context.response_len += response->body ().size ();
149136 LOG_DEBUG () << " Got response body_size=" << response->body ().size ();
150- auto ts3 = std::chrono::system_clock::now ();
137+ const auto ts3 = std::chrono::system_clock::now ();
151138 LOG_INFO () << " timings create=" << std::chrono::duration_cast<std::chrono::microseconds>(ts2 - ts1).count ()
152139 << " us "
153140 << " response=" << std::chrono::duration_cast<std::chrono::microseconds>(ts3 - ts2).count ()
@@ -171,20 +158,20 @@ void DoWork(const Config& config, const std::vector<std::string>& urls) {
171158 http_client.SetMultiplexingEnabled (config.multiplexing );
172159 if (config.max_host_connections > 0 ) http_client.SetMaxHostConnections (config.max_host_connections );
173160
174- WorkerContext worker_context{{0 }, 2000 , 0 , std::ref ( http_client) , config, urls};
161+ WorkerContext worker_context{{0 }, 2000 , 0 , http_client, config, urls};
175162
176163 std::vector<engine::TaskWithResult<void >> tasks;
177164 tasks.resize (config.coroutines );
178- auto tp1 = std::chrono::system_clock::now ();
165+ const auto tp1 = std::chrono::system_clock::now ();
179166 LOG_WARNING () << " Creating workers..." ;
180- for (size_t i = 0 ; i < config.coroutines ; ++i) {
167+ for (std:: size_t i = 0 ; i < config.coroutines ; ++i) {
181168 tasks[i] = engine::AsyncNoSpan (tp, &Worker, std::ref (worker_context));
182169 }
183170 LOG_WARNING () << " All workers are started " << std::this_thread::get_id ();
184171
185- for ( auto & task : tasks) task. Get ( );
172+ engine::GetAll (tasks );
186173
187- auto tp2 = std::chrono::system_clock::now ();
174+ const auto tp2 = std::chrono::system_clock::now ();
188175 auto rps = config.count * 1000 / (std::chrono::duration_cast<std::chrono::milliseconds>(tp2 - tp1).count () + 1 );
189176
190177 std::cerr << std::endl;
@@ -194,26 +181,21 @@ void DoWork(const Config& config, const std::vector<std::string>& urls) {
194181
195182} // namespace
196183
197- int main (int argc, char * argv[]) {
184+ int main (int argc, const char * const argv[]) {
198185 const Config config = ParseConfig (argc, argv);
199186
200- logging::LoggerPtr logger;
201187 const auto level = logging::LevelFromString (config.log_level );
202- if (!config.logfile .empty ()) {
203- logger = logging::MakeFileLogger (" default" , config.logfile , logging::Format::kTskv , level);
204- } else {
205- logger = logging::MakeStderrLogger (" default" , logging::Format::kTskv , level);
206- }
207- logging::DefaultLoggerGuard guard{logger};
188+ const logging::DefaultLoggerGuard guard{
189+ config.logfile .empty () ? logging::MakeStderrLogger (" default" , logging::Format::kTskv , level)
190+ : logging::MakeFileLogger (" default" , config.logfile , logging::Format::kTskv , level)};
208191
209192 LOG_WARNING () << " Starting using requests=" << config.count << " coroutines=" << config.coroutines
210193 << " timeout=" << config.timeout_ms << " ms" ;
211194 LOG_WARNING () << " multiplexing =" << (config.multiplexing ? " enabled" : " disabled" )
212195 << " max_host_connections=" << config.max_host_connections ;
213196
214197 const std::vector<std::string> urls = ReadUrls (config);
215-
216198 engine::RunStandalone (config.worker_threads , [&]() { DoWork (config, urls); });
217199
218- LOG_WARNING () << " Exit " ;
200+ LOG_WARNING () << " Finished " ;
219201}
0 commit comments