From 245faabfce9350e7279891ddccbb2f3d86dfd493 Mon Sep 17 00:00:00 2001 From: antao Date: Wed, 30 Jan 2019 12:27:16 +0800 Subject: [PATCH 1/2] Use the user space spinlock for performance reasons --- lib/inc/drogon/HttpTypes.h | 27 +++++++++++++++++++ lib/src/HttpControllersRouter.cc | 4 +-- lib/src/HttpControllersRouter.h | 3 ++- lib/src/HttpResponseImpl.cc | 6 ++--- lib/src/HttpResponseImpl.h | 11 ++++---- lib/src/HttpSimpleControllersRouter.cc | 6 ++--- lib/src/HttpSimpleControllersRouter.h | 5 +++- orm_lib/src/DbClientImpl.cc | 2 +- orm_lib/src/DbClientImpl.h | 4 +-- orm_lib/src/sqlite3_impl/Sqlite3Connection.cc | 6 ++--- orm_lib/src/sqlite3_impl/Sqlite3Connection.h | 5 ++-- 11 files changed, 56 insertions(+), 23 deletions(-) diff --git a/lib/inc/drogon/HttpTypes.h b/lib/inc/drogon/HttpTypes.h index e53d4e0e..b3be0b1f 100644 --- a/lib/inc/drogon/HttpTypes.h +++ b/lib/inc/drogon/HttpTypes.h @@ -12,10 +12,19 @@ */ #pragma once +#include +#include +#include namespace drogon { +#if (CXX_STD > 14) +typedef std::shared_mutex SharedMutex; +#else +typedef std::shared_timed_mutex SharedMutex; +#endif + enum HttpStatusCode { //rfc2616-6.1.1 @@ -106,4 +115,22 @@ enum HttpMethod Invalid }; +class SpinLock +{ + public: + SpinLock(std::atomic_flag &flag) : _flag(flag) + { + while (_flag.test_and_set(std::memory_order_acquire)) + { + } + } + ~SpinLock() + { + _flag.clear(); + } + + private: + std::atomic_flag &_flag; +}; + } // namespace drogon diff --git a/lib/src/HttpControllersRouter.cc b/lib/src/HttpControllersRouter.cc index 088e331b..5701a12a 100644 --- a/lib/src/HttpControllersRouter.cc +++ b/lib/src/HttpControllersRouter.cc @@ -219,7 +219,7 @@ void HttpControllersRouter::doControllerHandler(const CtrlBinderPtr &ctrlBinderP { HttpResponsePtr responsePtr; { - std::lock_guard guard(ctrlBinderPtr->_binderMtx); + SpinLock guard(ctrlBinderPtr->_binderMtx); responsePtr = ctrlBinderPtr->_responsePtr; } @@ -282,7 +282,7 @@ void HttpControllersRouter::doControllerHandler(const CtrlBinderPtr &ctrlBinderP //cache the response; std::dynamic_pointer_cast(resp)->makeHeaderString(); { - std::lock_guard guard(ctrlBinderPtr->_binderMtx); + SpinLock guard(ctrlBinderPtr->_binderMtx); ctrlBinderPtr->_responsePtr = resp; } } diff --git a/lib/src/HttpControllersRouter.h b/lib/src/HttpControllersRouter.h index e047e608..9c30f285 100644 --- a/lib/src/HttpControllersRouter.h +++ b/lib/src/HttpControllersRouter.h @@ -23,6 +23,7 @@ #include #include #include +#include namespace drogon { @@ -49,7 +50,7 @@ class HttpControllersRouter : public trantor::NonCopyable std::vector> _filters; std::vector _parameterPlaces; std::map _queryParametersPlaces; - std::mutex _binderMtx; + std::atomic_flag _binderMtx = ATOMIC_FLAG_INIT; std::shared_ptr _responsePtr; }; typedef std::shared_ptr CtrlBinderPtr; diff --git a/lib/src/HttpResponseImpl.cc b/lib/src/HttpResponseImpl.cc index 31288edb..d2e392ef 100755 --- a/lib/src/HttpResponseImpl.cc +++ b/lib/src/HttpResponseImpl.cc @@ -347,14 +347,14 @@ std::shared_ptr HttpResponseImpl::renderToString() const _httpStringDate = now.microSecondsSinceEpoch() / MICRO_SECONDS_PRE_SEC; auto newDate = getHttpFullDate(now); { - std::lock_guard lock(*_httpStringMutex); + SpinLock lock(*_httpStringMutex); _httpString = std::make_shared(*_httpString); memcpy((void *)&(*_httpString)[_datePos], newDate, strlen(newDate)); return _httpString; } } { - std::lock_guard lock(*_httpStringMutex); + SpinLock lock(*_httpStringMutex); return _httpString; } } @@ -390,7 +390,7 @@ std::shared_ptr HttpResponseImpl::renderToString() const httpString->append(*_bodyPtr); if (_expriedTime >= 0) { - std::lock_guard lock(*_httpStringMutex); + SpinLock lock(*_httpStringMutex); _datePos = datePos; _httpString = httpString; } diff --git a/lib/src/HttpResponseImpl.h b/lib/src/HttpResponseImpl.h index 06d9a270..fe0f3ccc 100755 --- a/lib/src/HttpResponseImpl.h +++ b/lib/src/HttpResponseImpl.h @@ -24,6 +24,7 @@ #include #include #include +#include using namespace trantor; namespace drogon @@ -40,8 +41,9 @@ class HttpResponseImpl : public HttpResponse _leftBodyLength(0), _currentChunkLength(0), _bodyPtr(new std::string()), - _httpStringMutex(new std::mutex()) + _httpStringMutex(new std::atomic_flag()) { + _httpStringMutex->clear(); } virtual HttpStatusCode statusCode() override { @@ -52,7 +54,7 @@ class HttpResponseImpl : public HttpResponse { return _creationDate; } - + virtual void setStatusCode(HttpStatusCode code) override { _statusCode = code; @@ -356,12 +358,11 @@ class HttpResponseImpl : public HttpResponse void gunzip() { auto gunzipBody = gzipDecompress(_bodyPtr); - if(gunzipBody) + if (gunzipBody) _bodyPtr = gunzipBody; } protected: - static std::string web_response_code_to_string(int code); void makeHeaderString(const std::shared_ptr &headerStringPtr) const; @@ -387,7 +388,7 @@ class HttpResponseImpl : public HttpResponse std::shared_ptr _fullHeaderString; mutable std::shared_ptr _httpString; - mutable std::shared_ptr _httpStringMutex; + mutable std::shared_ptr _httpStringMutex; mutable std::string::size_type _datePos = std::string::npos; mutable int64_t _httpStringDate = -1; diff --git a/lib/src/HttpSimpleControllersRouter.cc b/lib/src/HttpSimpleControllersRouter.cc index 1a2177e6..4a317371 100644 --- a/lib/src/HttpSimpleControllersRouter.cc +++ b/lib/src/HttpSimpleControllersRouter.cc @@ -125,8 +125,8 @@ void HttpSimpleControllersRouter::doControllerHandler(SimpleControllerRouterItem { HttpResponsePtr responsePtr; { - //maybe update controller,so we use lock_guard to protect; - std::lock_guard guard(item._mutex); + //Maybe update the _responsePtr, so we use shared_lock to protect; + SpinLock guard(item._mutex); responsePtr = item._responsePtr; } if (responsePtr && (responsePtr->expiredTime() == 0 || (trantor::Date::now() < responsePtr->creationDate().after(responsePtr->expiredTime())))) @@ -154,7 +154,7 @@ void HttpSimpleControllersRouter::doControllerHandler(SimpleControllerRouterItem //cache the response; std::dynamic_pointer_cast(resp)->makeHeaderString(); { - std::lock_guard guard(item._mutex); + SpinLock guard(item._mutex); item._responsePtr = resp; } } diff --git a/lib/src/HttpSimpleControllersRouter.h b/lib/src/HttpSimpleControllersRouter.h index 3fd7cd43..3a592ff0 100644 --- a/lib/src/HttpSimpleControllersRouter.h +++ b/lib/src/HttpSimpleControllersRouter.h @@ -24,9 +24,12 @@ #include #include #include +#include +#include namespace drogon { + class HttpAppFrameworkImpl; class HttpControllersRouter; class HttpSimpleControllersRouter : public trantor::NonCopyable @@ -53,7 +56,7 @@ class HttpSimpleControllersRouter : public trantor::NonCopyable std::vector _validMethodsFlags; std::shared_ptr _controller; std::shared_ptr _responsePtr; - std::mutex _mutex; + std::atomic_flag _mutex = ATOMIC_FLAG_INIT; }; std::unordered_map _simpCtrlMap; std::mutex _simpCtrlMutex; diff --git a/orm_lib/src/DbClientImpl.cc b/orm_lib/src/DbClientImpl.cc index 3c38baf1..9b85d4e3 100644 --- a/orm_lib/src/DbClientImpl.cc +++ b/orm_lib/src/DbClientImpl.cc @@ -81,7 +81,7 @@ DbClientImpl::DbClientImpl(const std::string &connInfo, const size_t connNum, Cl } else if (type == ClientType::Sqlite3) { - _sharedMutexPtr = std::make_shared(); + _sharedMutexPtr = std::make_shared(); assert(_sharedMutexPtr); auto loop = _loops.getNextLoop(); loop->runInLoop([this]() { diff --git a/orm_lib/src/DbClientImpl.h b/orm_lib/src/DbClientImpl.h index 389d0443..3e0199d3 100644 --- a/orm_lib/src/DbClientImpl.h +++ b/orm_lib/src/DbClientImpl.h @@ -15,6 +15,7 @@ #pragma once #include "DbConnection.h" +#include #include #include #include @@ -23,7 +24,6 @@ #include #include #include -#include namespace drogon { @@ -48,7 +48,7 @@ class DbClientImpl : public DbClient, public std::enable_shared_from_this _sharedMutexPtr; + std::shared_ptr _sharedMutexPtr; void execSql(const DbConnectionPtr &conn, std::string &&sql, diff --git a/orm_lib/src/sqlite3_impl/Sqlite3Connection.cc b/orm_lib/src/sqlite3_impl/Sqlite3Connection.cc index e55ca21a..f1cba3d3 100644 --- a/orm_lib/src/sqlite3_impl/Sqlite3Connection.cc +++ b/orm_lib/src/sqlite3_impl/Sqlite3Connection.cc @@ -34,7 +34,7 @@ void Sqlite3Connection::onError(const std::string &sql, const std::function &sharedMutex) +Sqlite3Connection::Sqlite3Connection(trantor::EventLoop *loop, const std::string &connInfo, const std::shared_ptr &sharedMutex) : DbConnection(loop), _sharedMutexPtr(sharedMutex) { @@ -190,14 +190,14 @@ void Sqlite3Connection::execSqlInQueue(const std::string &sql, if (sqlite3_stmt_readonly(stmt)) { //Readonly, hold read lock; - std::shared_lock lock(*_sharedMutexPtr); + std::shared_lock lock(*_sharedMutexPtr); r = stmtStep(stmt, resultPtr, columnNum); stmtPtr.reset(); } else { //Hold write lock - std::unique_lock lock(*_sharedMutexPtr); + std::unique_lock lock(*_sharedMutexPtr); r = stmtStep(stmt, resultPtr, columnNum); if (r == SQLITE_DONE) { diff --git a/orm_lib/src/sqlite3_impl/Sqlite3Connection.h b/orm_lib/src/sqlite3_impl/Sqlite3Connection.h index 75db9999..e7125572 100644 --- a/orm_lib/src/sqlite3_impl/Sqlite3Connection.h +++ b/orm_lib/src/sqlite3_impl/Sqlite3Connection.h @@ -17,6 +17,7 @@ #include "../DbConnection.h" #include "Sqlite3ResultImpl.h" #include +#include #include #include #include @@ -38,7 +39,7 @@ typedef std::shared_ptr Sqlite3ConnectionPtr; class Sqlite3Connection : public DbConnection, public std::enable_shared_from_this { public: - Sqlite3Connection(trantor::EventLoop *loop, const std::string &connInfo, const std::shared_ptr &sharedMutex); + Sqlite3Connection(trantor::EventLoop *loop, const std::string &connInfo, const std::shared_ptr &sharedMutex); virtual void execSql(std::string &&sql, size_t paraNum, @@ -64,7 +65,7 @@ class Sqlite3Connection : public DbConnection, public std::enable_shared_from_th int stmtStep(sqlite3_stmt *stmt, const std::shared_ptr &resultPtr, int columnNum); trantor::EventLoopThread _loopThread; std::shared_ptr _conn; - std::shared_ptr _sharedMutexPtr; + std::shared_ptr _sharedMutexPtr; }; } // namespace orm From acd56f2cee50bf8c363530cfc6498974016cda33 Mon Sep 17 00:00:00 2001 From: an-tao <20741618@qq.com> Date: Wed, 30 Jan 2019 13:09:48 +0800 Subject: [PATCH 2/2] Add memory order to the list of clear() parameters --- lib/inc/drogon/HttpTypes.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/inc/drogon/HttpTypes.h b/lib/inc/drogon/HttpTypes.h index b3be0b1f..f926912b 100644 --- a/lib/inc/drogon/HttpTypes.h +++ b/lib/inc/drogon/HttpTypes.h @@ -126,7 +126,7 @@ class SpinLock } ~SpinLock() { - _flag.clear(); + _flag.clear(std::memory_order_release); } private: