From daa3c820878f8e189120cf9359caf8b2359d61ca Mon Sep 17 00:00:00 2001 From: ipkn Date: Sun, 17 Aug 2014 05:35:21 -0400 Subject: improve performance by 2x change to io_service per CPU model --- include/http_server.h | 59 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 44 insertions(+), 15 deletions(-) (limited to 'include/http_server.h') diff --git a/include/http_server.h b/include/http_server.h index 73f62f0..6dc845a 100644 --- a/include/http_server.h +++ b/include/http_server.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -23,53 +24,80 @@ namespace crow public: Server(Handler* handler, uint16_t port, uint16_t concurrency = 1) : acceptor_(io_service_, tcp::endpoint(asio::ip::address(), port)), - socket_(io_service_), signals_(io_service_, SIGINT, SIGTERM), handler_(handler), concurrency_(concurrency), port_(port) { - do_accept(); } void run() { + if (concurrency_ < 0) + concurrency_ = 1; + + for(int i = 0; i < concurrency_; i++) + io_service_pool_.emplace_back(new boost::asio::io_service()); + std::vector> v; for(uint16_t i = 0; i < concurrency_; i ++) v.push_back( - std::async(std::launch::async, [this]{ + std::async(std::launch::async, [this, i]{ auto& timer_queue = detail::dumb_timer_queue::get_current_dumb_timer_queue(); - timer_queue.set_io_service(io_service_); - while(!io_service_.stopped()) - { + timer_queue.set_io_service(*io_service_pool_[i]); + boost::asio::deadline_timer timer(*io_service_pool_[i]); + timer.expires_from_now(boost::posix_time::seconds(1)); + std::function handler; + handler = [&](const boost::system::error_code& ec){ + if (ec) + return; timer_queue.process(); - io_service_.poll_one(); - } + timer.expires_from_now(boost::posix_time::seconds(1)); + timer.async_wait(handler); + }; + timer.async_wait(handler); + io_service_pool_[i]->run(); })); - CROW_LOG_INFO << server_name_ << " server is running, local port " << port_; signals_.async_wait( [&](const boost::system::error_code& error, int signal_number){ - io_service_.stop(); + stop(); }); - + + do_accept(); + + v.push_back(std::async(std::launch::async, [this]{ + io_service_.run(); + CROW_LOG_INFO << "Exiting."; + })); } void stop() { io_service_.stop(); + for(auto& io_service:io_service_pool_) + io_service->stop(); } private: + asio::io_service& pick_io_service() + { + // TODO load balancing + roundrobin_index_++; + if (roundrobin_index_ >= io_service_pool_.size()) + roundrobin_index_ = 0; + return *io_service_pool_[roundrobin_index_]; + } + void do_accept() { - acceptor_.async_accept(socket_, - [this](boost::system::error_code ec) + auto p = new Connection(pick_io_service(), handler_, server_name_); + acceptor_.async_accept(p->socket(), + [this, p](boost::system::error_code ec) { if (!ec) { - auto p = new Connection(std::move(socket_), handler_, server_name_); p->start(); } do_accept(); @@ -78,13 +106,14 @@ namespace crow private: asio::io_service io_service_; + std::vector> io_service_pool_; tcp::acceptor acceptor_; - tcp::socket socket_; boost::asio::signal_set signals_; Handler* handler_; uint16_t concurrency_{1}; std::string server_name_ = "Crow/0.1"; uint16_t port_; + unsigned int roundrobin_index_{}; }; } -- cgit v1.2.3-54-g00ecf