Skip to content

Commit 8f89523

Browse files
committed
Bug#36796808 scalability of HTTP request handling is limited
The http-request router doesn't scale to large number of parallel requests. At 32 parallel connections handling GET requests to /no-such-file, the requests per seconds is more or less the same as at 16 parallel connections (on a 128 core machine). Running `perf` shows that a lot time is spent in the mutex of HttpRequestRouter::find_route_handler(). Change ====== - changed the std::mutex around the request-handlers into a std::shared_mutex to allow parallel reads Requests/s over parallel connections: +----+----------+----------+-------+ | | Before | After | Diff | +----+----------+----------+-------+ | 1 | 11483.5 | 11703.0 | +2% | | 2 | 23964.0 | 24591.0 | +2% | | 4 | 39662.5 | 41094.5 | +3% | | 8 | 72266.5 | 76064.0 | +5% | | 16 | 86481.0 | 148098.5 | +72% | | 32 | 98067.5 | 289619.0 | +195% | | 64 | 102125.5 | 504629.0 | +394% | +----+----------+----------+-------+ Change-Id: I1481d7700182c67e2a83d9408455b4980615d759
1 parent 6a71d96 commit 8f89523

File tree

2 files changed

+12
-9
lines changed

2 files changed

+12
-9
lines changed

router/src/http/src/http_request_router.cc

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,15 @@ using BaseRequestHandlerPtr = HttpRequestRouter::BaseRequestHandlerPtr;
4848
void HttpRequestRouter::append(const std::string &url_regex_str,
4949
std::unique_ptr<http::base::RequestHandler> cb) {
5050
log_debug("adding route for regex: %s", url_regex_str.c_str());
51-
std::lock_guard<std::mutex> lock(route_mtx_);
51+
std::unique_lock lock(route_mtx_);
52+
5253
request_handlers_.emplace_back(RouterData{
5354
url_regex_str, std::regex{url_regex_str, std::regex_constants::extended},
5455
std::move(cb)});
5556
}
5657

5758
void HttpRequestRouter::remove(const void *handler_id) {
58-
std::lock_guard<std::mutex> lock(route_mtx_);
59+
std::unique_lock lock(route_mtx_);
5960

6061
for (auto it = request_handlers_.begin(); it != request_handlers_.end();) {
6162
if (it->handler.get() == handler_id) {
@@ -69,7 +70,8 @@ void HttpRequestRouter::remove(const void *handler_id) {
6970

7071
void HttpRequestRouter::remove(const std::string &url_regex_str) {
7172
log_debug("removing route for regex: %s", url_regex_str.c_str());
72-
std::lock_guard<std::mutex> lock(route_mtx_);
73+
std::unique_lock lock(route_mtx_);
74+
7375
for (auto it = request_handlers_.begin(); it != request_handlers_.end();) {
7476
if (it->url_regex_str == url_regex_str) {
7577
it = request_handlers_.erase(it);
@@ -98,13 +100,15 @@ void HttpRequestRouter::handler_not_found(http::base::Request &req) {
98100
void HttpRequestRouter::set_default_route(
99101
std::unique_ptr<http::base::RequestHandler> cb) {
100102
log_debug("adding default route");
101-
std::lock_guard<std::mutex> lock(route_mtx_);
103+
std::unique_lock lock(route_mtx_);
104+
102105
default_route_ = std::move(cb);
103106
}
104107

105108
void HttpRequestRouter::clear_default_route() {
106109
log_debug("removing default route");
107-
std::lock_guard<std::mutex> lock(route_mtx_);
110+
std::unique_lock lock(route_mtx_);
111+
108112
default_route_ = nullptr;
109113
}
110114

@@ -147,7 +151,7 @@ void HttpRequestRouter::route(http::base::Request &req) {
147151

148152
BaseRequestHandlerPtr HttpRequestRouter::find_route_handler(
149153
const std::string &path) {
150-
std::lock_guard<std::mutex> lock(route_mtx_);
154+
std::shared_lock lock(route_mtx_);
151155

152156
for (auto &request_handler : request_handlers_) {
153157
if (std::regex_search(path, request_handler.url_regex)) {

router/src/http/src/http_request_router.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@
2727
#define ROUTER_SRC_HTTP_SRC_HTTP_REQUEST_ROUTER_H_
2828

2929
#include <memory>
30-
#include <mutex>
3130
#include <regex>
31+
#include <shared_mutex>
3232
#include <string>
3333
#include <thread>
3434
#include <vector>
@@ -44,7 +44,6 @@ class HttpRequestRouter : public http::server::RequestHandlerInterface {
4444
using RequestHandler = http::base::RequestHandler;
4545
using BaseRequestHandlerPtr = std::shared_ptr<http::base::RequestHandler>;
4646

47-
public:
4847
void append(const std::string &url_regex_str,
4948
std::unique_ptr<RequestHandler> cb);
5049
void remove(const void *handler_id);
@@ -72,7 +71,7 @@ class HttpRequestRouter : public http::server::RequestHandlerInterface {
7271
BaseRequestHandlerPtr default_route_;
7372
std::string require_realm_;
7473

75-
std::mutex route_mtx_;
74+
mutable std::shared_mutex route_mtx_;
7675
};
7776

7877
#endif // ROUTER_SRC_HTTP_SRC_HTTP_REQUEST_ROUTER_H_

0 commit comments

Comments
 (0)