LibSourcey Event-driven Networking with Libuv

Kam Low

LibSourcey Logo LibSourcey began it’s life built on the brilliant Poco C++ libraries, but once we began developing mission critical server-side code like our ICE stack (TURN/STUN server), HTTP server and Symple messaging, the old multi-thread design just wouldn’t cut it.

Poco is a well designed and cleanly coded C++ library with cross-platform implementations for just about everything you would ever need to build most console applications, but it’s not without it’s niggles:

  • Poco clearly isn’t meant for high-performance networking, which is evident in the thread-per-connection model used in the HTTP stack.
  • Overuse or private methods and members which make it almost impossible to extend and override even the most basic functionality.

Performance issues aside, some things about Poco just didn’t seem as open or intuitive as they could be, which is why we turned to libuv and C++11.

Most developers know about Node.js, which is a runtime that makes it a sinch to quickly and easily deploy high performance networking applications in the cloud using good ol’ JavaScript. The underlying library which powers Node.js’s cross-platform event-driven awesomeness is of course libuv, and now it powers LibSourcey too.

The great thing about working with libuv is that it’s event-based rather than thread-based, so rather than relying on threads for asynchronicity, the event loop is used instead. From a performance standpoint the thread-per-core model is ideal for evented IO, that is; one event loop, per thread, per CPU core. This is by no means a hard and fast rule, since the use of threads is still appropriate for long blocking tasks, although it’s definitely something to aspire towards when writing your code.

Since the event loop runs in a single thread very little synchronization is required, other than to pass data between threads which is sometimes unavoidable (such as when using a load balancer). By refactoring the LibSourcey codebase to use an event-based architecture we were able to decrease the use of synchronization primitives by 90%.

Event-driven programming has helped us write better code and yield massive performance gains, especially for networking applications. If you want to save your sanity then stop writing multi-threaded code - your code will be better, faster, and easier to debug. There’s a lot more to talk about here, but that’s a song for another day.

comments powered by Disqus