You need to sign in before continuing.
Commit b4971936d4c21e459255ce4abc05abeb56e35d7a
1 parent
696e1246
No-wait mode
User can now enable no-wait mode, which chooses whether we use the EVRUN_NOWAIT flag in ev_run. The default is off, so that we don't use 100% CPU. Note added in tutorial to enable when performance is critical. Added to the speed test examples. Bump to 0.2.1. Remove patch number from HISTORY entry - that's what the git log is for. Make note on minor release.
Showing
11 changed files
with
54 additions
and
11 deletions
CMakeLists.txt
| ... | ... | @@ -3,7 +3,7 @@ project(redox) |
| 3 | 3 | |
| 4 | 4 | set(REDOX_VERSION_MAJOR 0) |
| 5 | 5 | set(REDOX_VERSION_MINOR 2) |
| 6 | -set(REDOX_VERSION_PATCH 0) | |
| 6 | +set(REDOX_VERSION_PATCH 1) | |
| 7 | 7 | set(REDOX_VERSION_STRING ${REDOX_VERSION_MAJOR}.${REDOX_VERSION_MINOR}.${REDOX_VERSION_PATCH}) |
| 8 | 8 | |
| 9 | 9 | option(lib "Build Redox as a dynamic library." ON) | ... | ... |
HISTORY.md
| 1 | 1 | # Release History |
| 2 | 2 | |
| 3 | -## 0.2.0 (2015-01-31) | |
| 3 | +## 0.2 (2015-01-31) | |
| 4 | 4 | * Move to vector of strings as input, to handle arbitrary data better and |
| 5 | 5 | improve speed. |
| 6 | 6 | * Add doxygen docs. |
| 7 | 7 | * Move all init code out of constructors into .connect methods. |
| 8 | 8 | |
| 9 | -## 0.1.0 (2015-01-27) | |
| 9 | +## 0.1 (2015-01-27) | |
| 10 | 10 | First versioned release after many nights of segfaults and memory leaks. |
| 11 | 11 | |
| 12 | -## 0.0.0 (2014-12-20) | |
| 12 | +## 0.0 (2014-12-20) | |
| 13 | 13 | Desire to use Redis in C++, but unhappy with existing clients. | ... | ... |
README.md
| ... | ... | @@ -41,8 +41,7 @@ local Redis server. |
| 41 | 41 | * `speed_test_sync` over TCP: **21,072 commands/s** |
| 42 | 42 | * `speed_test_sync` over Unix socket: **24,911 commands/s** |
| 43 | 43 | |
| 44 | -Results are comparable to that of a mid-range laptop. On a high-end machine, performance | |
| 45 | -can be much higher. | |
| 44 | +A mid-range laptop gives comparable results. Numbers can be much higher on a high-end machine. | |
| 46 | 45 | |
| 47 | 46 | ## Tutorial |
| 48 | 47 | This section introduces the main features of redox. Look in `examples/` for more inspiration. |
| ... | ... | @@ -231,6 +230,12 @@ a vector of strings as needed by its API. `rdx.strToVec("GET foo")` |
| 231 | 230 | will return an `std::vector<std::string>` containing `GET` and `foo` |
| 232 | 231 | as entries. `rdx.vecToStr({"GET", "foo"})` will return the string `GET foo`. |
| 233 | 232 | |
| 233 | +#### No-Wait Mode | |
| 234 | +Redox provides a no-wait mode, which tells the event loop not to sleep | |
| 235 | +in between processing events. It means that the event thread will run | |
| 236 | +at 100% CPU, but it can greatly improve performance when critical. It is | |
| 237 | +disabled by default and can be enabled with `rdx.noWait(true);`. | |
| 238 | + | |
| 234 | 239 | ## Reply types |
| 235 | 240 | These the available template parameters in redox and the Redis |
| 236 | 241 | [return types](http://redis.io/topics/protocol) they can hold. | ... | ... |
examples/lpush_benchmark.cpp
examples/speed_test_async.cpp
examples/speed_test_async_multi.cpp
examples/speed_test_pubsub.cpp
examples/speed_test_sync.cpp
include/redox/client.hpp
| ... | ... | @@ -82,6 +82,18 @@ public: |
| 82 | 82 | ~Redox(); |
| 83 | 83 | |
| 84 | 84 | /** |
| 85 | + * Enables or disables 'no-wait' mode. If enabled, no-wait mode means that the | |
| 86 | + * event loop does not pause in between processing events. It can greatly increase | |
| 87 | + * the throughput (commands per second),but means that the event thread will run at | |
| 88 | + * 100% CPU. Enable when performance is critical and you can spare a core. Default | |
| 89 | + * is off. | |
| 90 | + * | |
| 91 | + * Implementation note: When enabled, the event thread calls libev's ev_run in a | |
| 92 | + * loop with the EVRUN_NOWAIT flag. | |
| 93 | + */ | |
| 94 | + void noWait(bool state); | |
| 95 | + | |
| 96 | + /** | |
| 85 | 97 | * Connects to Redis over TCP and starts an event loop in a separate thread. Returns |
| 86 | 98 | * true once everything is ready, or false on failure. |
| 87 | 99 | */ |
| ... | ... | @@ -340,6 +352,9 @@ private: |
| 340 | 352 | // Dynamically allocated libev event loop |
| 341 | 353 | struct ev_loop* evloop_; |
| 342 | 354 | |
| 355 | + // No-wait mode for high-performance | |
| 356 | + std::atomic_bool nowait_ = {false}; | |
| 357 | + | |
| 343 | 358 | // Asynchronous watchers |
| 344 | 359 | ev_async watcher_command_; // For processing commands |
| 345 | 360 | ev_async watcher_stop_; // For breaking the loop | ... | ... |
include/redox/subscriber.hpp
src/client.cpp
| ... | ... | @@ -200,6 +200,12 @@ bool Redox::initHiredis() { |
| 200 | 200 | return true; |
| 201 | 201 | } |
| 202 | 202 | |
| 203 | +void Redox::noWait(bool state) { | |
| 204 | + if(state) logger_.info() << "No-wait mode enabled."; | |
| 205 | + else logger_.info() << "No-wait mode disabled."; | |
| 206 | + nowait_ = state; | |
| 207 | +} | |
| 208 | + | |
| 203 | 209 | void breakEventLoop(struct ev_loop* loop, ev_async* async, int revents) { |
| 204 | 210 | ev_break(loop, EVBREAK_ALL); |
| 205 | 211 | } |
| ... | ... | @@ -237,12 +243,14 @@ void Redox::runEventLoop() { |
| 237 | 243 | running_ = true; |
| 238 | 244 | running_waiter_.notify_one(); |
| 239 | 245 | |
| 240 | - // Run the event loop | |
| 241 | - // TODO this hogs resources, but ev_run(evloop_) without | |
| 242 | - // the manual loop is slower. Maybe use a CV to run sparsely | |
| 243 | - // unless there are commands to process? | |
| 246 | + // Run the event loop, using NOWAIT if enabled for maximum | |
| 247 | + // throughput by avoiding any sleeping | |
| 244 | 248 | while (!to_exit_) { |
| 245 | - ev_run(evloop_, EVRUN_NOWAIT); | |
| 249 | + if(nowait_) { | |
| 250 | + ev_run(evloop_, EVRUN_NOWAIT); | |
| 251 | + } else { | |
| 252 | + ev_run(evloop_); | |
| 253 | + } | |
| 246 | 254 | } |
| 247 | 255 | |
| 248 | 256 | logger_.info() << "Stop signal detected. Closing down event loop."; | ... | ... |