Commit cb37f24f13758ce21f8db7cad87b4a1bb3070789
1 parent
a8a81ee7
Add unix sockets constructor
Showing
4 changed files
with
53 additions
and
18 deletions
README.md
| @@ -22,7 +22,8 @@ high-performance applications. It is built on top of [hiredis](https://github.co | @@ -22,7 +22,8 @@ high-performance applications. It is built on top of [hiredis](https://github.co | ||
| 22 | ## Performance Benchmarks | 22 | ## Performance Benchmarks |
| 23 | Benchmarks are given by averaging the results of five trials of various programs | 23 | Benchmarks are given by averaging the results of five trials of various programs |
| 24 | in `examples/`. The results are on an AWS t2.medium instance running Ubuntu 14.04 (64-bit). | 24 | in `examples/`. The results are on an AWS t2.medium instance running Ubuntu 14.04 (64-bit). |
| 25 | -During these tests, Redox communicated with a local Redis server over TCP. | 25 | +During these tests, Redox communicated with a local Redis server over TCP. Results are |
| 26 | +slightly faster using Unix sockets. | ||
| 26 | 27 | ||
| 27 | * 100 repeating asynchronous commands (`speed_test_async_multi`): **710,014 commands/s** | 28 | * 100 repeating asynchronous commands (`speed_test_async_multi`): **710,014 commands/s** |
| 28 | * One repeating asynchronous command (`speed_test_async`): **195,159 commands/s** | 29 | * One repeating asynchronous command (`speed_test_async`): **195,159 commands/s** |
src/command.hpp
| @@ -70,7 +70,7 @@ public: | @@ -70,7 +70,7 @@ public: | ||
| 70 | */ | 70 | */ |
| 71 | void free(); | 71 | void free(); |
| 72 | 72 | ||
| 73 | - void process_reply(); | 73 | + void process_reply(redisReply* r); |
| 74 | 74 | ||
| 75 | ev_timer* get_timer() { | 75 | ev_timer* get_timer() { |
| 76 | std::lock_guard<std::mutex> lg(timer_guard); | 76 | std::lock_guard<std::mutex> lg(timer_guard); |
| @@ -94,7 +94,6 @@ private: | @@ -94,7 +94,6 @@ private: | ||
| 94 | ev_timer timer; | 94 | ev_timer timer; |
| 95 | std::mutex timer_guard; | 95 | std::mutex timer_guard; |
| 96 | 96 | ||
| 97 | - | ||
| 98 | // Make sure we don't free resources until details taken care of | 97 | // Make sure we don't free resources until details taken care of |
| 99 | std::mutex free_guard; | 98 | std::mutex free_guard; |
| 100 | 99 | ||
| @@ -120,10 +119,11 @@ Command<ReplyT>::Command( | @@ -120,10 +119,11 @@ Command<ReplyT>::Command( | ||
| 120 | } | 119 | } |
| 121 | 120 | ||
| 122 | template<class ReplyT> | 121 | template<class ReplyT> |
| 123 | -void Command<ReplyT>::process_reply() { | 122 | +void Command<ReplyT>::process_reply(redisReply* r) { |
| 124 | 123 | ||
| 125 | free_guard.lock(); | 124 | free_guard.lock(); |
| 126 | 125 | ||
| 126 | + reply_obj = r; | ||
| 127 | invoke_callback(); | 127 | invoke_callback(); |
| 128 | 128 | ||
| 129 | pending--; | 129 | pending--; |
src/redox.cpp
| @@ -45,18 +45,14 @@ void Redox::disconnected_callback(const redisAsyncContext *ctx, int status) { | @@ -45,18 +45,14 @@ void Redox::disconnected_callback(const redisAsyncContext *ctx, int status) { | ||
| 45 | if(rdx->user_connection_callback) rdx->user_connection_callback(rdx->connect_state); | 45 | if(rdx->user_connection_callback) rdx->user_connection_callback(rdx->connect_state); |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | -Redox::Redox( | ||
| 49 | - const string& host, const int port, | ||
| 50 | - std::function<void(int)> connection_callback | ||
| 51 | -) : host(host), port(port), user_connection_callback(connection_callback) { | ||
| 52 | - | ||
| 53 | - // libev setup | 48 | +void Redox::init_ev() { |
| 54 | signal(SIGPIPE, SIG_IGN); | 49 | signal(SIGPIPE, SIG_IGN); |
| 55 | evloop = ev_loop_new(EVFLAG_AUTO); | 50 | evloop = ev_loop_new(EVFLAG_AUTO); |
| 56 | ev_set_userdata(evloop, (void*)this); // Back-reference | 51 | ev_set_userdata(evloop, (void*)this); // Back-reference |
| 52 | +} | ||
| 53 | + | ||
| 54 | +void Redox::init_hiredis() { | ||
| 57 | 55 | ||
| 58 | - // Create a redisAsyncContext | ||
| 59 | - ctx = redisAsyncConnect(host.c_str(), port); | ||
| 60 | ctx->data = (void*)this; // Back-reference | 56 | ctx->data = (void*)this; // Back-reference |
| 61 | 57 | ||
| 62 | if (ctx->err) { | 58 | if (ctx->err) { |
| @@ -74,6 +70,32 @@ Redox::Redox( | @@ -74,6 +70,32 @@ Redox::Redox( | ||
| 74 | redisAsyncSetDisconnectCallback(ctx, Redox::disconnected_callback); | 70 | redisAsyncSetDisconnectCallback(ctx, Redox::disconnected_callback); |
| 75 | } | 71 | } |
| 76 | 72 | ||
| 73 | +Redox::Redox( | ||
| 74 | + const string& host, const int port, | ||
| 75 | + std::function<void(int)> connection_callback | ||
| 76 | +) : host(host), port(port), user_connection_callback(connection_callback) { | ||
| 77 | + | ||
| 78 | + init_ev(); | ||
| 79 | + | ||
| 80 | + // Connect over TCP | ||
| 81 | + ctx = redisAsyncConnect(host.c_str(), port); | ||
| 82 | + | ||
| 83 | + init_hiredis(); | ||
| 84 | +} | ||
| 85 | + | ||
| 86 | +Redox::Redox( | ||
| 87 | + const std::string& path, | ||
| 88 | + std::function<void(int)> connection_callback = nullptr | ||
| 89 | +) : path(path), user_connection_callback(connection_callback) { | ||
| 90 | + | ||
| 91 | + init_ev(); | ||
| 92 | + | ||
| 93 | + // Connect over unix sockets | ||
| 94 | + ctx = redisAsyncConnectUnix(path.c_str()); | ||
| 95 | + | ||
| 96 | + init_hiredis(); | ||
| 97 | +} | ||
| 98 | + | ||
| 77 | void Redox::run_event_loop() { | 99 | void Redox::run_event_loop() { |
| 78 | 100 | ||
| 79 | // Events to connect to Redox | 101 | // Events to connect to Redox |
| @@ -200,8 +222,7 @@ void Redox::command_callback(redisAsyncContext *ctx, void *r, void *privdata) { | @@ -200,8 +222,7 @@ void Redox::command_callback(redisAsyncContext *ctx, void *r, void *privdata) { | ||
| 200 | return; | 222 | return; |
| 201 | } | 223 | } |
| 202 | 224 | ||
| 203 | - c->reply_obj = reply_obj; | ||
| 204 | - c->process_reply(); | 225 | + c->process_reply(reply_obj); |
| 205 | 226 | ||
| 206 | // Increment the Redox object command counter | 227 | // Increment the Redox object command counter |
| 207 | rdx->cmd_count++; | 228 | rdx->cmd_count++; |
| @@ -340,7 +361,7 @@ void Redox::command(const string& cmd) { | @@ -340,7 +361,7 @@ void Redox::command(const string& cmd) { | ||
| 340 | 361 | ||
| 341 | bool Redox::command_blocking(const string& cmd) { | 362 | bool Redox::command_blocking(const string& cmd) { |
| 342 | Command<redisReply*>* c = command_blocking<redisReply*>(cmd); | 363 | Command<redisReply*>* c = command_blocking<redisReply*>(cmd); |
| 343 | - bool succeeded = (c->status() == REDOX_OK); | 364 | + bool succeeded = c->ok(); |
| 344 | c->free(); | 365 | c->free(); |
| 345 | return succeeded; | 366 | return succeeded; |
| 346 | } | 367 | } |
src/redox.hpp
| @@ -48,6 +48,14 @@ public: | @@ -48,6 +48,14 @@ public: | ||
| 48 | const int port = REDIS_DEFAULT_PORT, | 48 | const int port = REDIS_DEFAULT_PORT, |
| 49 | std::function<void(int)> connection_callback = nullptr | 49 | std::function<void(int)> connection_callback = nullptr |
| 50 | ); | 50 | ); |
| 51 | + | ||
| 52 | + /** | ||
| 53 | + * Initialize everything, connect over unix sockets to a Redis server. | ||
| 54 | + */ | ||
| 55 | + Redox( | ||
| 56 | + const std::string& path, | ||
| 57 | + std::function<void(int)> connection_callback | ||
| 58 | + ); | ||
| 51 | ~Redox(); | 59 | ~Redox(); |
| 52 | 60 | ||
| 53 | /** | 61 | /** |
| @@ -173,10 +181,17 @@ public: | @@ -173,10 +181,17 @@ public: | ||
| 173 | 181 | ||
| 174 | private: | 182 | private: |
| 175 | 183 | ||
| 176 | - // Redox server | 184 | + // Redox server over TCP |
| 177 | std::string host; | 185 | std::string host; |
| 178 | int port; | 186 | int port; |
| 179 | 187 | ||
| 188 | + // Redox server over unix | ||
| 189 | + std::string path; | ||
| 190 | + | ||
| 191 | + // Setup code for the constructors | ||
| 192 | + void init_ev(); | ||
| 193 | + void init_hiredis(); | ||
| 194 | + | ||
| 180 | // Manage connection state | 195 | // Manage connection state |
| 181 | std::atomic_int connect_state = {REDOX_NOT_YET_CONNECTED}; | 196 | std::atomic_int connect_state = {REDOX_NOT_YET_CONNECTED}; |
| 182 | std::mutex connect_lock; | 197 | std::mutex connect_lock; |
| @@ -315,9 +330,7 @@ Command<ReplyT>* Redox::command_blocking(const std::string& cmd) { | @@ -315,9 +330,7 @@ Command<ReplyT>* Redox::command_blocking(const std::string& cmd) { | ||
| 315 | 0, 0, false // No repeats, don't free memory | 330 | 0, 0, false // No repeats, don't free memory |
| 316 | ); | 331 | ); |
| 317 | 332 | ||
| 318 | - // Wait until a callback is invoked | ||
| 319 | cv.wait(lk, [&status] { return status != REDOX_UNINIT; }); | 333 | cv.wait(lk, [&status] { return status != REDOX_UNINIT; }); |
| 320 | - | ||
| 321 | c->reply_val = val; | 334 | c->reply_val = val; |
| 322 | c->reply_status = status; | 335 | c->reply_status = status; |
| 323 | 336 |