Talks

Cables! Cables! Cables!

wroc_love.rb 2018

00:00:23.910 First of all, thanks to Stefan for the great talk on Rails performance and for saying multiple times that Ruby is slow. I don't need to repeat this because my talk is related to performance and some weaker parts of Ruby. For the first time here, my name is Vladimir, and I came all the way from Moscow. I think I brought the snow with me—sorry for that! I expected nicer weather here, but I hope to experience spring weather soon. It's all the same apart from programming in Ruby, Erlang, Golang, and Crystal. I do a lot of open source work, and you can find me on GitHub and Twitter. I work at a company called Evil Martians, where we do a lot of fun and exciting work for both big companies and small startups during product development. We also do a lot of open-source work and write about it in our blog, which features cool illustrations.
00:01:07.930 Now, let's talk about why I'm here. I'm looking for someone with experience in Action Cable, which is a not-so-new framework that's been around for almost three years now from the Rails family. I'd like to share its good and bad parts, along with some scary stories and information about other cables that are out there in the wild.
00:01:54.780 First of all, what do we mean by 'cable'? By 'cable,' I mean any tool or framework that allows you to build real-time web applications. A real-time web application is one that allows a user to receive information as soon as it appears in the system from other users, without requiring periodic checks for updates. This type of communication is asynchronous and fast, with typical examples including chat applications. When it comes to Ruby, there are many Ruby solutions available to help build real-time applications. Some of them are already obsolete, while others are brand new and perhaps still unknown to many. Even as a Ruby developer, when faced with building something real-time, developers often opt for non-Ruby solutions, mainly because Ruby is perceived as slow.
00:03:08.280 As we know, Ruby has limitations, including the Global Interpreter Lock (GIL), which affects concurrency. This brings up the question: would you choose Ruby for your real-time applications, or would you rather not even try? Perhaps there's a possibility that we can write performant, concurrent applications using Ruby—but not solely in Ruby, and that's a question I hope to answer during my talk.
00:03:50.380 Let's first discuss Action Cable, which is our main subject for today. Action Cable can be divided into several parts. First, we have a server that handles all low-level WebSocket manipulations, including parsing the WebSocket protocol and sending and receiving messages. Then, we have a broadcaster part, which is responsible for sending messages to clients that subscribe to particular streams, essentially defining communication channels. To handle all this, we have what can be described as a channels framework, which is utilized for writing your code. These are the three main pillars of Action Cable. Additionally, we have clients, including built-in ones in Rails, such as a JavaScript client, and third-party clients for different platforms.
00:05:39.680 Let’s talk about the good and bad parts of Action Cable as I see them. What makes Action Cable attractive for Rails developers is that it is built into Rails. If you're creating a Rails app, you have a ready-made solution for real-time functionality without needing to worry about it. One more significant advantage is that, unlike previous solutions, such as Action Cable alternatives based on EventMachine, you don’t need to run a separate Ruby process to handle WebSockets. Everything operates within your regular web server process, making it easy to work with and highly compatible. However, I have a question for the audience: how many out there are using Action Cable or Rails?
00:06:44.880 There are some challenges with Action Cable that shouldn't be overlooked. Firstly, it solely relies on WebSockets as a protocol and lacks failover capabilities. While there are still users on outdated technologies that don’t support WebSockets, this is not the primary concern for Action Cable users unless you're specifically building applications for that 3% of users. The main reason people are apprehensive about using Action Cable is due to its memory usage, which is influenced by Ruby’s limitations. For instance, when benchmarking simple WebSocket applications, we find that Ruby applications require substantially more memory than similar implementations using other technologies. Although memory usage has improved in Ruby version 2.5 compared to 2.3, it's still a critical factor worth discussing.
00:08:03.000 The second critical aspect is real-time performance. When evaluating page load performance, we consider the time it takes for the server to broadcast a message to all clients subscribed to a stream. Latency is a crucial metric for many applications, especially in contexts like chat applications, where you don't want several seconds of delay in communication. We have a benchmark, developed by a reputable company, that measures real-time performance. This benchmark indicates that for a basic version of Action Cable with only two workers — the minimum necessary for adequate performance — latency increases significantly with thousands of clients. Although some may argue that thousands of clients is still a manageable number, the performance degrades quickly based on user population scaling.
00:09:36.300 As we increase the number of workers to eight, thereby deploying on an eight-CPU machine for this benchmark, we observe an improvement—though it's still evident that Action Cable lags behind more suitable technologies. This raises the concern about whether Action Cable is appropriate for high-load situations, such as handling millions of connections with low latency, especially since Ruby itself is not optimized for this type of application. Therefore, if you require such performance, it may be time to explore other frameworks.
00:11:27.140 Let me show you a quick CPU usage example while I take a sip of water. What you're witnessing is the CPU utilization with Action Cable on a 16-core Amazon instance. Although not severely heavy, there isn’t much room for other applications on this machine. Now, transitioning from theoretical benchmarks to real-life applications, let’s discuss an interesting case: a platform called QUIT.com, which manages and monitors equestrian shows. While I'm not a fan of horse sports, I found that this platform is heavily reliant on WebSockets for real-time monitoring services, translating events occurring live during these busy weekends with thousands of connections.
00:12:40.900 I spoke with the owners of this startup, who shared their experiences as they navigated through various technologies before ultimately switching to a new solution I’ll refer to as X. They encountered serious memory issues when using Action Cable under high loads, requiring them to scale to over 21 Heroku dynos, each with 1GB of RAM, and they consistently faced memory core exceeded exceptions in their application.
00:14:01.020 After migrating to a different cable solution, their resource requirements drastically decreased—tenfold. They now only require four dynos, allowing them to save significantly on hosting costs. The transition was accomplished in a matter of weeks, which is impressive given the scale of their application and legacy code.
00:15:06.610 The new solution involves AnyCable, which extends Action Cable to enhance performance and reduce resource consumption. The concept is straightforward: extract the performance-heavy parts of Action Cable—for instance, the WebSocket server—away from slow Ruby implementations, leveraging more efficient programming languages for handling asynchronous messaging. By using technologies like gRPC and HTTP/2 along with a Redis message broker, AnyCable becomes a robust solution capable of managing numerous connections efficiently. I would encourage anyone interested to learn more about it, as it provides many opportunities for optimizing Action Cable's performance.
00:16:27.570 I want to summarize the potential of AnyCable in comparison to Action Cable. While thinly substituting Action Cable won’t suffice for high-performance projects, AnyCable can serve as a practical solution for Ruby developers looking to build high-concurrency applications.
00:17:45.840 Let’s touch on an intriguing concept, zero disconnect deployment, which addresses the issue encountered during Action Cable updates. When deploying a new version of an Action Cable application, clients typically get disconnected. This means that when the server restarts, all clients will have to reconnect, which could lead to potential data loss. However, with a well-architected proxy for the WebSocket server, the deployment process can be executed smoothly without disrupting client connections, improving overall application performance, especially for applications that deploy frequently.
00:19:24.300 AnyCable also offers advanced analytics, allowing developers to monitor application performance and resource usage. This is key for identifying potential outages and optimizing performance as usage scales, providing detailed insights into the number of active clients and the overall health of the application. There is a wealth of resources and documentation available for AnyCable, and I encourage those interested to check them out. Before wrapping up my talk, I'll take a moment to address any questions about how AnyCable works, its features, and its applicability in various scenarios.
00:20:57.950 Many of you may wonder why there are two implementations of AnyCable—one in Golang and another in Erlang. The answer is that I initially wrote a prototype in Golang over a year ago for quick development but later attempted to write one in Erlang. However, I faced challenges due to the lack of a reliable gRPC library for Erlang, so I ultimately decided to maintain the Golang version, which proved to be much easier for Ruby developers to use.
00:25:29.820 In summary, there are also alternatives like LightCable. It’s a lightweight solution that implements the Action Cable protocol without dependencies on Rails or ActiveSupport. Additionally, it can be configured to work with AnyCable for enhanced performance. This opens up new avenues for Ruby developers who wish to create real-time applications with reduced complexity. Lastly, I want to acknowledge the contributions of creators from projects like Odin and Blaze, who aim to offer resource-efficient alternatives for building Ruby applications. These innovations are vital in shaping future solutions for Ruby and real-time web development.
00:29:22.430 In conclusion, Ruby can indeed be used for real-time applications, but for high-performance needs, additional technologies might be necessary alongside Ruby to achieve the desired results. Many developers use Action Cable for small or experimental projects. However, as the needs scale, developers have the option to migrate to solutions like AnyCable, LightCable, or other emerging technologies that allow for higher performance without compromising on the capabilities of Ruby as a programming language. If anyone is interested in stickers or has questions, please feel free to reach out to me after the talk. Thank you.