diff --git a/README.md b/README.md index a6a308b..60302b7 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,8 @@ high-performance applications. It is built on top of [hiredis](https://github.co ## Performance Benchmarks Benchmarks are given by averaging the results of five trials of various programs in `examples/`. The results are on an AWS t2.medium instance running Ubuntu 14.04 (64-bit). -During these tests, Redox communicated with a local Redis server over TCP. +During these tests, Redox communicated with a local Redis server over TCP. Results are +slightly faster using Unix sockets. * 100 repeating asynchronous commands (`speed_test_async_multi`): **710,014 commands/s** * One repeating asynchronous command (`speed_test_async`): **195,159 commands/s** diff --git a/src/command.hpp b/src/command.hpp index 25af2a6..8064e85 100644 --- a/src/command.hpp +++ b/src/command.hpp @@ -70,7 +70,7 @@ public: */ void free(); - void process_reply(); + void process_reply(redisReply* r); ev_timer* get_timer() { std::lock_guard lg(timer_guard); @@ -94,7 +94,6 @@ private: ev_timer timer; std::mutex timer_guard; - // Make sure we don't free resources until details taken care of std::mutex free_guard; @@ -120,10 +119,11 @@ Command::Command( } template -void Command::process_reply() { +void Command::process_reply(redisReply* r) { free_guard.lock(); + reply_obj = r; invoke_callback(); pending--; diff --git a/src/redox.cpp b/src/redox.cpp index 0040459..1fa1640 100644 --- a/src/redox.cpp +++ b/src/redox.cpp @@ -45,18 +45,14 @@ void Redox::disconnected_callback(const redisAsyncContext *ctx, int status) { if(rdx->user_connection_callback) rdx->user_connection_callback(rdx->connect_state); } -Redox::Redox( - const string& host, const int port, - std::function connection_callback -) : host(host), port(port), user_connection_callback(connection_callback) { - - // libev setup +void Redox::init_ev() { signal(SIGPIPE, SIG_IGN); evloop = ev_loop_new(EVFLAG_AUTO); ev_set_userdata(evloop, (void*)this); // Back-reference +} + +void Redox::init_hiredis() { - // Create a redisAsyncContext - ctx = redisAsyncConnect(host.c_str(), port); ctx->data = (void*)this; // Back-reference if (ctx->err) { @@ -74,6 +70,32 @@ Redox::Redox( redisAsyncSetDisconnectCallback(ctx, Redox::disconnected_callback); } +Redox::Redox( + const string& host, const int port, + std::function connection_callback +) : host(host), port(port), user_connection_callback(connection_callback) { + + init_ev(); + + // Connect over TCP + ctx = redisAsyncConnect(host.c_str(), port); + + init_hiredis(); +} + +Redox::Redox( + const std::string& path, + std::function connection_callback = nullptr +) : path(path), user_connection_callback(connection_callback) { + + init_ev(); + + // Connect over unix sockets + ctx = redisAsyncConnectUnix(path.c_str()); + + init_hiredis(); +} + void Redox::run_event_loop() { // Events to connect to Redox @@ -200,8 +222,7 @@ void Redox::command_callback(redisAsyncContext *ctx, void *r, void *privdata) { return; } - c->reply_obj = reply_obj; - c->process_reply(); + c->process_reply(reply_obj); // Increment the Redox object command counter rdx->cmd_count++; @@ -340,7 +361,7 @@ void Redox::command(const string& cmd) { bool Redox::command_blocking(const string& cmd) { Command* c = command_blocking(cmd); - bool succeeded = (c->status() == REDOX_OK); + bool succeeded = c->ok(); c->free(); return succeeded; } diff --git a/src/redox.hpp b/src/redox.hpp index 93fbb75..f1287a9 100644 --- a/src/redox.hpp +++ b/src/redox.hpp @@ -48,6 +48,14 @@ public: const int port = REDIS_DEFAULT_PORT, std::function connection_callback = nullptr ); + + /** + * Initialize everything, connect over unix sockets to a Redis server. + */ + Redox( + const std::string& path, + std::function connection_callback + ); ~Redox(); /** @@ -173,10 +181,17 @@ public: private: - // Redox server + // Redox server over TCP std::string host; int port; + // Redox server over unix + std::string path; + + // Setup code for the constructors + void init_ev(); + void init_hiredis(); + // Manage connection state std::atomic_int connect_state = {REDOX_NOT_YET_CONNECTED}; std::mutex connect_lock; @@ -315,9 +330,7 @@ Command* Redox::command_blocking(const std::string& cmd) { 0, 0, false // No repeats, don't free memory ); - // Wait until a callback is invoked cv.wait(lk, [&status] { return status != REDOX_UNINIT; }); - c->reply_val = val; c->reply_status = status;