aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoripknHama <ipknhama@gmail.com>2014-08-16 11:55:26 +0900
committeripknHama <ipknhama@gmail.com>2014-08-16 11:55:26 +0900
commitef51b97d8b5647a2a474b382e8772711cdfd8327 (patch)
tree2cdd483b0cd569d6a66bf760d54ad0b15fd4c8fb
parentc5cbb3ff54119855e63dff9666fd490a92f0db76 (diff)
downloadcrow-ef51b97d8b5647a2a474b382e8772711cdfd8327.tar.gz
crow-ef51b97d8b5647a2a474b382e8772711cdfd8327.zip
Change to custom timer implementation to increase performance
-rw-r--r--include/dumb_timer_queue.h62
-rw-r--r--include/http_connection.h51
-rw-r--r--include/http_server.h12
-rw-r--r--include/routing.h5
4 files changed, 110 insertions, 20 deletions
diff --git a/include/dumb_timer_queue.h b/include/dumb_timer_queue.h
new file mode 100644
index 0000000..185725e
--- /dev/null
+++ b/include/dumb_timer_queue.h
@@ -0,0 +1,62 @@
+#pragma once
+
+#include <boost/asio.hpp>
+#include <deque>
+#include <functional>
+#include <chrono>
+#include <thread>
+
+namespace crow
+{
+ namespace detail
+ {
+ // fast timer queue for fixed tick value.
+ class dumb_timer_queue
+ {
+ public:
+ // tls based queue to avoid locking
+ static dumb_timer_queue& get_current_dumb_timer_queue()
+ {
+ thread_local dumb_timer_queue q;
+ return q;
+ }
+
+ void add(std::function<void()> f)
+ {
+ dq_.emplace_back(std::chrono::steady_clock::now(), std::move(f));
+ }
+
+ void process()
+ {
+ if (!io_service_)
+ return;
+ auto now = std::chrono::steady_clock::now();
+ while(!dq_.empty())
+ {
+ auto& x = dq_.front();
+ if (now - x.first < std::chrono::seconds(tick))
+ break;
+ if (x.second)
+ {
+ io_service_->post(std::move(x.second));
+ }
+ dq_.pop_front();
+ }
+ }
+
+ void set_io_service(boost::asio::io_service& io_service)
+ {
+ io_service_ = &io_service;
+ }
+
+ private:
+ dumb_timer_queue() noexcept
+ {
+ }
+
+ int tick{5};
+ boost::asio::io_service* io_service_{};
+ std::deque<std::pair<decltype(std::chrono::steady_clock::now()), std::function<void()>>> dq_;
+ };
+ }
+}
diff --git a/include/http_connection.h b/include/http_connection.h
index 5de6ec8..a25924d 100644
--- a/include/http_connection.h
+++ b/include/http_connection.h
@@ -13,6 +13,7 @@
#include "http_response.h"
#include "logging.h"
#include "settings.h"
+#include "dumb_timer_queue.h"
namespace crow
{
@@ -29,8 +30,7 @@ namespace crow
: socket_(std::move(socket)),
handler_(handler),
parser_(this),
- server_name_(server_name),
- deadline_(socket_.get_io_service())
+ server_name_(server_name)
{
#ifdef CROW_ENABLE_DEBUG
connectionCount ++;
@@ -41,6 +41,7 @@ namespace crow
~Connection()
{
res.complete_request_handler_ = nullptr;
+ cancel_deadline_timer();
#ifdef CROW_ENABLE_DEBUG
connectionCount --;
CROW_LOG_DEBUG << "Connection closed, total " << connectionCount << ", " << this;
@@ -96,8 +97,7 @@ namespace crow
if (!is_invalid_request)
{
- deadline_.cancel();
- //auto self = this->shared_from_this();
+ cancel_deadline_timer();
res.complete_request_handler_ = [this]{ this->complete_request(); };
res.is_alive_helper_ = [this]()->bool{ return socket_.is_open(); };
handler_->handle(req, res);
@@ -241,7 +241,7 @@ namespace crow
if (!ec)
{
bool ret = parser_.feed(buffer_.data(), bytes_transferred);
- if (ret)
+ if (ret && socket_.is_open() && !close_connection_)
{
do_read();
error_while_reading = false;
@@ -250,10 +250,11 @@ namespace crow
if (error_while_reading)
{
- deadline_.cancel();
+ cancel_deadline_timer();
parser_.done();
socket_.close();
is_reading = false;
+ CROW_LOG_DEBUG << this << " from read(1)";
check_destory();
}
else
@@ -277,15 +278,21 @@ namespace crow
if (close_connection_)
{
socket_.close();
+ CROW_LOG_DEBUG << this << " from write(1)";
+ check_destory();
}
}
else
+ {
+ CROW_LOG_DEBUG << this << " from write(2)";
check_destory();
+ }
});
}
void check_destory()
{
+ CROW_LOG_DEBUG << this << " is_reading " << is_reading << " is_writing " << is_writing;
if (!is_reading && !is_writing)
{
CROW_LOG_DEBUG << this << " delete (idle) ";
@@ -293,21 +300,34 @@ namespace crow
}
}
+ void cancel_deadline_timer()
+ {
+ if (timer_cancel_helper)
+ {
+ *timer_cancel_helper = true;
+ timer_cancel_helper.release();
+ }
+ }
+
void start_deadline(int timeout = 5)
{
- deadline_.expires_from_now(boost::posix_time::seconds(timeout));
- //auto self = this->shared_from_this();
- deadline_.async_wait([this](const boost::system::error_code& ec)
+ auto& timer_queue = detail::dumb_timer_queue::get_current_dumb_timer_queue();
+ cancel_deadline_timer();
+
+ timer_cancel_helper.reset(new bool{false});
+ bool* p_is_cancelled = timer_cancel_helper.get();
+ timer_queue.add([p_is_cancelled, this]
{
- if (ec || !socket_.is_open())
+ if (*p_is_cancelled)
{
+ delete p_is_cancelled;
return;
}
- bool is_deadline_passed = deadline_.expires_at() <= boost::asio::deadline_timer::traits_type::now();
- if (is_deadline_passed)
+ if (!socket_.is_open())
{
- socket_.close();
+ return;
}
+ socket_.close();
});
}
@@ -315,7 +335,7 @@ namespace crow
tcp::socket socket_;
Handler* handler_;
- std::array<char, 8192> buffer_;
+ std::array<char, 4096> buffer_;
HTTPParser<Connection> parser_;
response res;
@@ -328,7 +348,8 @@ namespace crow
std::string content_length_;
std::string date_str_;
- boost::asio::deadline_timer deadline_;
+ //boost::asio::deadline_timer deadline_;
+ std::unique_ptr<bool> timer_cancel_helper;
bool is_reading{};
bool is_writing{};
diff --git a/include/http_server.h b/include/http_server.h
index 228cc8c..73f62f0 100644
--- a/include/http_server.h
+++ b/include/http_server.h
@@ -10,6 +10,7 @@
#include "http_connection.h"
#include "datetime.h"
#include "logging.h"
+#include "dumb_timer_queue.h"
namespace crow
{
@@ -36,8 +37,15 @@ namespace crow
std::vector<std::future<void>> v;
for(uint16_t i = 0; i < concurrency_; i ++)
v.push_back(
- std::async(std::launch::async, [this]{io_service_.run();})
- );
+ std::async(std::launch::async, [this]{
+ 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.process();
+ io_service_.poll_one();
+ }
+ }));
CROW_LOG_INFO << server_name_ << " server is running, local port " << port_;
diff --git a/include/routing.h b/include/routing.h
index 28700c1..b07c2c3 100644
--- a/include/routing.h
+++ b/include/routing.h
@@ -125,9 +125,8 @@ namespace crow
);
return;
}
-#ifdef CROW_ENABLE_LOGGING
- std::cerr << "ERROR cannot find handler" << std::endl;
-#endif
+ CROW_LOG_DEBUG << "ERROR cannot find handler" << std::endl;
+
// we already found matched url; this is server error
cparams.res = response(500);
}