mirror of
https://gitee.com/an-tao/drogon.git
synced 2024-12-04 12:47:42 +08:00
Merge pull request #51 from an-tao/dev-spinlock
Use user space spinlock to improve performance
This commit is contained in:
commit
f374429227
@ -12,10 +12,19 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <drogon/config.h>
|
||||
#include <shared_mutex>
|
||||
#include <atomic>
|
||||
|
||||
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(std::memory_order_release);
|
||||
}
|
||||
|
||||
private:
|
||||
std::atomic_flag &_flag;
|
||||
};
|
||||
|
||||
} // namespace drogon
|
||||
|
@ -219,7 +219,7 @@ void HttpControllersRouter::doControllerHandler(const CtrlBinderPtr &ctrlBinderP
|
||||
{
|
||||
HttpResponsePtr responsePtr;
|
||||
{
|
||||
std::lock_guard<std::mutex> 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<HttpResponseImpl>(resp)->makeHeaderString();
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(ctrlBinderPtr->_binderMtx);
|
||||
SpinLock guard(ctrlBinderPtr->_binderMtx);
|
||||
ctrlBinderPtr->_responsePtr = resp;
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
#include <memory>
|
||||
#include <atomic>
|
||||
|
||||
namespace drogon
|
||||
{
|
||||
@ -49,7 +50,7 @@ class HttpControllersRouter : public trantor::NonCopyable
|
||||
std::vector<std::shared_ptr<HttpFilterBase>> _filters;
|
||||
std::vector<size_t> _parameterPlaces;
|
||||
std::map<std::string, size_t> _queryParametersPlaces;
|
||||
std::mutex _binderMtx;
|
||||
std::atomic_flag _binderMtx = ATOMIC_FLAG_INIT;
|
||||
std::shared_ptr<HttpResponse> _responsePtr;
|
||||
};
|
||||
typedef std::shared_ptr<CtrlBinder> CtrlBinderPtr;
|
||||
|
@ -347,14 +347,14 @@ std::shared_ptr<std::string> HttpResponseImpl::renderToString() const
|
||||
_httpStringDate = now.microSecondsSinceEpoch() / MICRO_SECONDS_PRE_SEC;
|
||||
auto newDate = getHttpFullDate(now);
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(*_httpStringMutex);
|
||||
SpinLock lock(*_httpStringMutex);
|
||||
_httpString = std::make_shared<std::string>(*_httpString);
|
||||
memcpy((void *)&(*_httpString)[_datePos], newDate, strlen(newDate));
|
||||
return _httpString;
|
||||
}
|
||||
}
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(*_httpStringMutex);
|
||||
SpinLock lock(*_httpStringMutex);
|
||||
return _httpString;
|
||||
}
|
||||
}
|
||||
@ -390,7 +390,7 @@ std::shared_ptr<std::string> HttpResponseImpl::renderToString() const
|
||||
httpString->append(*_bodyPtr);
|
||||
if (_expriedTime >= 0)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(*_httpStringMutex);
|
||||
SpinLock lock(*_httpStringMutex);
|
||||
_datePos = datePos;
|
||||
_httpString = httpString;
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <atomic>
|
||||
|
||||
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<std::string> &headerStringPtr) const;
|
||||
|
||||
@ -387,7 +388,7 @@ class HttpResponseImpl : public HttpResponse
|
||||
std::shared_ptr<std::string> _fullHeaderString;
|
||||
|
||||
mutable std::shared_ptr<std::string> _httpString;
|
||||
mutable std::shared_ptr<std::mutex> _httpStringMutex;
|
||||
mutable std::shared_ptr<std::atomic_flag> _httpStringMutex;
|
||||
mutable std::string::size_type _datePos = std::string::npos;
|
||||
mutable int64_t _httpStringDate = -1;
|
||||
|
||||
|
@ -125,8 +125,8 @@ void HttpSimpleControllersRouter::doControllerHandler(SimpleControllerRouterItem
|
||||
{
|
||||
HttpResponsePtr responsePtr;
|
||||
{
|
||||
//maybe update controller,so we use lock_guard to protect;
|
||||
std::lock_guard<std::mutex> 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<HttpResponseImpl>(resp)->makeHeaderString();
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(item._mutex);
|
||||
SpinLock guard(item._mutex);
|
||||
item._responsePtr = resp;
|
||||
}
|
||||
}
|
||||
|
@ -24,9 +24,12 @@
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
#include <memory>
|
||||
#include <shared_mutex>
|
||||
#include <atomic>
|
||||
|
||||
namespace drogon
|
||||
{
|
||||
|
||||
class HttpAppFrameworkImpl;
|
||||
class HttpControllersRouter;
|
||||
class HttpSimpleControllersRouter : public trantor::NonCopyable
|
||||
@ -53,7 +56,7 @@ class HttpSimpleControllersRouter : public trantor::NonCopyable
|
||||
std::vector<int> _validMethodsFlags;
|
||||
std::shared_ptr<HttpSimpleControllerBase> _controller;
|
||||
std::shared_ptr<HttpResponse> _responsePtr;
|
||||
std::mutex _mutex;
|
||||
std::atomic_flag _mutex = ATOMIC_FLAG_INIT;
|
||||
};
|
||||
std::unordered_map<std::string, SimpleControllerRouterItem> _simpCtrlMap;
|
||||
std::mutex _simpCtrlMutex;
|
||||
|
@ -81,7 +81,7 @@ DbClientImpl::DbClientImpl(const std::string &connInfo, const size_t connNum, Cl
|
||||
}
|
||||
else if (type == ClientType::Sqlite3)
|
||||
{
|
||||
_sharedMutexPtr = std::make_shared<std::shared_timed_mutex>();
|
||||
_sharedMutexPtr = std::make_shared<SharedMutex>();
|
||||
assert(_sharedMutexPtr);
|
||||
auto loop = _loops.getNextLoop();
|
||||
loop->runInLoop([this]() {
|
||||
|
@ -15,6 +15,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "DbConnection.h"
|
||||
#include <drogon/HttpTypes.h>
|
||||
#include <drogon/orm/DbClient.h>
|
||||
#include <trantor/net/EventLoopThreadPool.h>
|
||||
#include <memory>
|
||||
@ -23,7 +24,6 @@
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
#include <list>
|
||||
#include <shared_mutex>
|
||||
|
||||
namespace drogon
|
||||
{
|
||||
@ -48,7 +48,7 @@ class DbClientImpl : public DbClient, public std::enable_shared_from_this<DbClie
|
||||
std::string _connInfo;
|
||||
size_t _connectNum;
|
||||
trantor::EventLoopThreadPool _loops;
|
||||
std::shared_ptr<std::shared_timed_mutex> _sharedMutexPtr;
|
||||
std::shared_ptr<SharedMutex> _sharedMutexPtr;
|
||||
|
||||
void execSql(const DbConnectionPtr &conn,
|
||||
std::string &&sql,
|
||||
|
@ -34,7 +34,7 @@ void Sqlite3Connection::onError(const std::string &sql, const std::function<void
|
||||
}
|
||||
}
|
||||
|
||||
Sqlite3Connection::Sqlite3Connection(trantor::EventLoop *loop, const std::string &connInfo, const std::shared_ptr<std::shared_timed_mutex> &sharedMutex)
|
||||
Sqlite3Connection::Sqlite3Connection(trantor::EventLoop *loop, const std::string &connInfo, const std::shared_ptr<SharedMutex> &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<std::shared_timed_mutex> lock(*_sharedMutexPtr);
|
||||
std::shared_lock<SharedMutex> lock(*_sharedMutexPtr);
|
||||
r = stmtStep(stmt, resultPtr, columnNum);
|
||||
stmtPtr.reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
//Hold write lock
|
||||
std::unique_lock<std::shared_timed_mutex> lock(*_sharedMutexPtr);
|
||||
std::unique_lock<SharedMutex> lock(*_sharedMutexPtr);
|
||||
r = stmtStep(stmt, resultPtr, columnNum);
|
||||
if (r == SQLITE_DONE)
|
||||
{
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "../DbConnection.h"
|
||||
#include "Sqlite3ResultImpl.h"
|
||||
#include <drogon/orm/DbClient.h>
|
||||
#include <drogon/HttpTypes.h>
|
||||
#include <trantor/utils/NonCopyable.h>
|
||||
#include <trantor/utils/SerialTaskQueue.h>
|
||||
#include <trantor/net/EventLoopThread.h>
|
||||
@ -38,7 +39,7 @@ typedef std::shared_ptr<Sqlite3Connection> Sqlite3ConnectionPtr;
|
||||
class Sqlite3Connection : public DbConnection, public std::enable_shared_from_this<Sqlite3Connection>
|
||||
{
|
||||
public:
|
||||
Sqlite3Connection(trantor::EventLoop *loop, const std::string &connInfo, const std::shared_ptr<std::shared_timed_mutex> &sharedMutex);
|
||||
Sqlite3Connection(trantor::EventLoop *loop, const std::string &connInfo, const std::shared_ptr<SharedMutex> &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<Sqlite3ResultImpl> &resultPtr, int columnNum);
|
||||
trantor::EventLoopThread _loopThread;
|
||||
std::shared_ptr<sqlite3> _conn;
|
||||
std::shared_ptr<std::shared_timed_mutex> _sharedMutexPtr;
|
||||
std::shared_ptr<SharedMutex> _sharedMutexPtr;
|
||||
};
|
||||
|
||||
} // namespace orm
|
||||
|
Loading…
Reference in New Issue
Block a user