From 83309b6391450e3803de0c2541b92e5547096f94 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Thu, 18 Sep 2014 23:56:01 +0900 Subject: [PATCH] nghttpx: Reduce epoll_ctl call --- src/shrpx_client_handler.cc | 4 ++-- src/shrpx_http2_session.cc | 8 ++++---- src/shrpx_http_downstream_connection.cc | 6 +++--- src/shrpx_io_control.cc | 10 +++++++--- src/shrpx_listen_handler.cc | 2 +- src/shrpx_worker.cc | 2 +- src/util.cc | 18 ++++++++++++++++++ src/util.h | 7 +++++++ 8 files changed, 43 insertions(+), 14 deletions(-) diff --git a/src/shrpx_client_handler.cc b/src/shrpx_client_handler.cc index de7e8d48..cff2ea3c 100644 --- a/src/shrpx_client_handler.cc +++ b/src/shrpx_client_handler.cc @@ -256,7 +256,7 @@ ClientHandler::ClientHandler(bufferevent *bev, CLOG(FATAL, this) << "bufferevent_add_to_rate_limit_group() failed"; } - bufferevent_enable(bev_, EV_READ | EV_WRITE); + util::bev_enable_unless(bev_, EV_READ | EV_WRITE); bufferevent_setwatermark(bev_, EV_READ, 0, SHRPX_READ_WATERMARK); set_upstream_timeouts(&get_config()->upstream_read_timeout, &get_config()->upstream_write_timeout); @@ -298,7 +298,7 @@ ClientHandler::~ClientHandler() bufferevent_remove_from_rate_limit_group(bev_); - bufferevent_disable(bev_, EV_READ | EV_WRITE); + util::bev_disable_unless(bev_, EV_READ | EV_WRITE); bufferevent_free(bev_); if(ssl_) { diff --git a/src/shrpx_http2_session.cc b/src/shrpx_http2_session.cc index 3052b8e5..54df9569 100644 --- a/src/shrpx_http2_session.cc +++ b/src/shrpx_http2_session.cc @@ -89,7 +89,7 @@ int Http2Session::disconnect() } if(bev_) { int fd = bufferevent_getfd(bev_); - bufferevent_disable(bev_, EV_READ | EV_WRITE); + util::bev_disable_unless(bev_, EV_READ | EV_WRITE); bufferevent_free(bev_); bev_ = nullptr; if(fd != -1) { @@ -219,7 +219,7 @@ int Http2Session::init_notification() close(sockpair[1]); return -1; } - bufferevent_enable(rdbev_, EV_READ); + util::bev_enable_unless(rdbev_, EV_READ); bufferevent_setcb(rdbev_, notify_readcb, nullptr, notify_eventcb, this); return 0; } @@ -417,7 +417,7 @@ int Http2Session::initiate_connection() close(fd); return SHRPX_ERR_NETWORK; } - bufferevent_enable(bev_, EV_READ); + util::bev_enable_unless(bev_, EV_READ); bufferevent_set_timeouts(bev_, &get_config()->downstream_read_timeout, &get_config()->downstream_write_timeout); @@ -534,7 +534,7 @@ int Http2Session::initiate_connection() } bufferevent_setwatermark(bev_, EV_READ, 0, SHRPX_READ_WATERMARK); - bufferevent_enable(bev_, EV_READ); + util::bev_enable_unless(bev_, EV_READ); bufferevent_setcb(bev_, readcb, writecb, eventcb, this); // Set timeout for HTTP2 session reset_timeouts(); diff --git a/src/shrpx_http_downstream_connection.cc b/src/shrpx_http_downstream_connection.cc index cf120589..849fb55e 100644 --- a/src/shrpx_http_downstream_connection.cc +++ b/src/shrpx_http_downstream_connection.cc @@ -54,7 +54,7 @@ HttpDownstreamConnection::HttpDownstreamConnection HttpDownstreamConnection::~HttpDownstreamConnection() { if(bev_) { - bufferevent_disable(bev_, EV_READ | EV_WRITE); + util::bev_disable_unless(bev_, EV_READ | EV_WRITE); bufferevent_free(bev_); } // Downstream and DownstreamConnection may be deleted @@ -127,7 +127,7 @@ int HttpDownstreamConnection::attach_downstream(Downstream *downstream) response_htp_.data = downstream_; bufferevent_setwatermark(bev_, EV_READ, 0, SHRPX_READ_WATERMARK); - bufferevent_enable(bev_, EV_READ); + util::bev_enable_unless(bev_, EV_READ); bufferevent_setcb(bev_, upstream->get_downstream_readcb(), upstream->get_downstream_writecb(), @@ -369,7 +369,7 @@ void HttpDownstreamConnection::detach_downstream(Downstream *downstream) } downstream_ = nullptr; ioctrl_.force_resume_read(); - bufferevent_enable(bev_, EV_READ); + util::bev_enable_unless(bev_, EV_READ); bufferevent_setcb(bev_, 0, 0, idle_eventcb, this); // On idle state, just enable read timeout. Normally idle downstream // connection will get EOF from the downstream server and closed. diff --git a/src/shrpx_io_control.cc b/src/shrpx_io_control.cc index 57fafd1d..a7e64d9f 100644 --- a/src/shrpx_io_control.cc +++ b/src/shrpx_io_control.cc @@ -26,6 +26,10 @@ #include +#include "util.h" + +using namespace nghttp2; + namespace shrpx { IOControl::IOControl(bufferevent *bev) @@ -45,7 +49,7 @@ void IOControl::pause_read(IOCtrlReason reason) { rdbits_ |= reason; if(bev_) { - bufferevent_disable(bev_, EV_READ); + util::bev_disable_unless(bev_, EV_READ); } } @@ -54,7 +58,7 @@ bool IOControl::resume_read(IOCtrlReason reason) rdbits_ &= ~reason; if(rdbits_ == 0) { if(bev_) { - bufferevent_enable(bev_, EV_READ); + util::bev_enable_unless(bev_, EV_READ); } return true; } else { @@ -66,7 +70,7 @@ void IOControl::force_resume_read() { rdbits_ = 0; if(bev_) { - bufferevent_enable(bev_, EV_READ); + util::bev_enable_unless(bev_, EV_READ); } } diff --git a/src/shrpx_listen_handler.cc b/src/shrpx_listen_handler.cc index a4d05dbc..165080ea 100644 --- a/src/shrpx_listen_handler.cc +++ b/src/shrpx_listen_handler.cc @@ -112,7 +112,7 @@ void worker_writecb(bufferevent *bev, void *ptr) // Disable bev so that this won' be called accidentally in the // future. - bufferevent_disable(bev, EV_READ | EV_WRITE); + util::bev_disable_unless(bev, EV_READ | EV_WRITE); } } // namespace #endif // NOTHREADS diff --git a/src/shrpx_worker.cc b/src/shrpx_worker.cc index 9191da7b..8c72de58 100644 --- a/src/shrpx_worker.cc +++ b/src/shrpx_worker.cc @@ -113,7 +113,7 @@ void Worker::run() http2session.get(), http1_connect_blocker.get()); - bufferevent_enable(bev.get(), EV_READ); + util::bev_enable_unless(bev.get(), EV_READ); bufferevent_setcb(bev.get(), readcb, nullptr, eventcb, receiver.get()); event_base_loop(evbase.get(), 0); diff --git a/src/util.cc b/src/util.cc index fb9dc45e..4724ea1a 100644 --- a/src/util.cc +++ b/src/util.cc @@ -657,6 +657,24 @@ char* get_exec_path(int argc, char **const argv, const char *cwd) return path; } +void bev_enable_unless(bufferevent *bev, int events) +{ + if((bufferevent_get_enabled(bev) & events) == events) { + return; + } + + bufferevent_enable(bev, events); +} + +void bev_disable_unless(bufferevent *bev, int events) +{ + if((bufferevent_get_enabled(bev) & events) == 0) { + return; + } + + bufferevent_disable(bev, events); +} + } // namespace util } // namespace nghttp2 diff --git a/src/util.h b/src/util.h index 8c52ecf3..d46ecd32 100644 --- a/src/util.h +++ b/src/util.h @@ -38,6 +38,7 @@ #include #include +#include #include "http-parser/http_parser.h" @@ -481,6 +482,12 @@ std::string ascii_dump(const uint8_t *data, size_t len); // it. char* get_exec_path(int argc, char **const argv, const char *cwd); +// These functions are provided to reduce epoll_ctl syscall. Avoid +// calling bufferevent_enable/disable() unless it is required by +// sniffing current enabled events. +void bev_enable_unless(bufferevent *bev, int events); +void bev_disable_unless(bufferevent *bev, int events); + } // namespace util } // namespace nghttp2