Comment by bradgessler
1 year ago
There's various PRs where Fiber adapters are making their way into the Rails stack. Rails 8 added a ton of support for Fibers, with the exception of ActionCable. There's a PR open for that, which I assume will land sometime soon.
Rails has been really slow to pick-up async/http-2. They don't know it yet, but Falcon and all async libraries Samuel is working on will probably be a huge them 1-2 years out when more people find out it means less infra has to be deployed to production environments. Right now folks are happy to deploy without Redis™ with the Solid stack, but a lot of that won't be needed if proper async support is baked into Rails.
There's been a lot of Fiber features being committed into the Ruby language that I barely understand, but have improved all of these async libraries over the past few years. That's finally starting to bear some fruit for people like myself who don't really understand all of those details, but understand the benefits.
It will happen, but these things tend to play out more slowly in Ruby, which is a feature or a bug depending on how you look at it.
> They don't know it yet,
This is so condescending... We perfectly know about the pros and cons of the fiber scheduler.
It's a very useful stack, but people, and you in particular, really need to stop selling it like it's the best thing since sliced bread. Async isn't a good fit for everything, and it's certainly not a good fit for the overwhelming majority of Rails applications.
I've heard from lots of folks in the Rails community that getting http/2 and streaming into Rails has been a slow and tedious process. I'm not saying it's going to be "a good fit for everything"—what I am saying is that it will be nice when we can run IO bound workloads in Rails without feeling like a fish out of water.
"it's certainly not a good fit for the overwhelming majority of Rails applications".
In my experience, most web applications are terminating HTTP connections from clients, then reaching out over a network to database servers, etc. to do work. This is very much IO-bound, so I'm not sure how this wouldn't be a good fit for most Rails applications.
> getting http/2 and streaming into Rails has been a slow and tedious process
Bringing http/2 all the way to the Rails process doesn't bring anything to the table. You're much better to terminate http2 or 3 with SSL at the LB.
> terminating HTTP connections from clients, then reaching out over a network to database servers, etc. to do work. This is very much IO-bound
It absolutely isn't unless your data access is really messed up (badly indexed queries or tons of N+1).
Even if you are just serializing the data you got from the DB down into JSON with little to no transformation, you'll likely end up spending more than 50% doing CPU work.
Look at all the reports of YJIT speeding up Rails applications by 15 to 30%. If Rails apps were truly IO bound like people claim, YJIT would have nothing to speedup.
Even if your app is 90% IO, you can slap Puma with 10 thread and will already suffer from contention. Async make sense when you'd need more than a dozen threads or so does. Before that it doesn't make a substantial difference. Like it would be great to use for Action Cable, but that's it.
> In my experience, most web applications are terminating HTTP connections from clients, then reaching out over a network to database servers, etc. to do work. This is very much IO-bound, so I'm not sure how this wouldn't be a good fit for most Rails applications.
Most rails applications are deployed using a multi-threaded application server such as Puma, a thread processes a single request and when it encounters IO (or calls out to a C function) the thread gives up its hold of the GVL and another thread can run. You can use 100% of your resources this way without the added complexity of parallelism within a single request.
Are there truly people out there that are terminating HTTP/2 at the application level? That's really quite surprising for anything serving production traffic.
I think the ActionCable PR is here: https://github.com/rails/rails/pull/50979 -- it seems like it's going well, but taking some time. I think that should be interesting for some use cases, but we'll have to see if/how that makes deployment/operations more complex. For example, if you're better off with the bulk of your app running w/ threads on Puma, would you run the ActionCable stuff w/ fibers on Falcon? Or maybe you just have an app that's doing mostly streaming of AI API responses or something?
Anyway, I'd be careful about over-promoting Falcon/Async, even as one of the relatively few people that's running in a large-ish production app. In my case, I'm doing a LOT of hanging waiting on API responses from weather data sources, and I want to transform the JSON and do some data point conversion in real time. So even in my case, I think it's better for me to switch (see https://github.com/socketry/async-examples for me doing some experiments) because I'm often waiting on API responses (in real time) that can take 1-2 seconds (!) but then I'm still doing some heavy CPU work reading and writing JSON blobs. I saw a pretty good speedup with YJIT, so I think I'm not entirely IO bound, if that makes sense.
I think it's great to have more options for those of us that love Ruby, so we don't need to switch to Node.js or something else for this kind of work. But I think it's likely that existing Rails apps (and typical CRUD Rails apps etc) will probably want to stick with a thread-based model. We'll see how it all shakes out over the next couple years, and I think you're right that it's exciting stuff. Between all the work on YJIT etc, and the possibilities for Node.js-type or Go type use-cases being possible/reasonable with Fibers, it's a great time for Ruby!