Hacker News new | past | comments | ask | show | jobs | submit login

My only concern is that none of his work is being picked up by Rails. As a matter of fact, it isn't just SW's work, the whole async story on ruby, it seems neither Fiber or Ractor has reached any mass adoption.



So first it's a bit annoying to read this when I busted my ass for several weeks to refactor Active Record to make it more compatible with the Fiber use case in 7.2.

But also there is very little benefit to it for the vast majority of Rails applications out there.

Unless you are doing micro-services or something like that, your typical Rails application isn't IO heavy enough to run more than 2 perhaps 3 threads before contending.

So the overwhelming majority of Rails applications wouldn't see any benefit from being served via falcon, quite the opposite.

Async is great to enable some use cases where people would have to reach to Node before, but Rails will never be a good solution for that, if you want to do some sort of light proxy or websocket notification thing, Rails isn't a good solution, you want something much lighter.


I will be curious to see what JRuby's fiber implementation is like in their upcoming version, currently I work on JRuby rails deployments with dozens of threads across hundreds of nodes. There's definitely some learning curves and tuning necessary when you have 40 threads in contention over a particular shared resource vs 3-5 on regular CRuby.


Wouldn't fibers work well for ActionCable applications? Lots of connections being kept alive, with sparse activity on them?


Yes. But just for the Action Cable parts, as in you'd deploy Action Cable standalone with falcon, and then keep Puma or whatever for the purely transactional requests.

If you don't, you'll notice that your Action Cable latency will be all over the place when a transaction request comes in.

It's acceptable for "hobby" use, but if you try to provide a good user experience with reasonable latency, you can't just collocate Action Cable and the rest of Rails in a single process.


Wow this sounds very smart.

Do you have any tutorial somewhere on how to use Falcon for this? I am getting some strange errors that would probably be covered in a basic tutorial already.


Have you actually benchmarked this and published the benchmarks somewhere?


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!


That's not completely accurate. Rails 7.2 added fiber support.

Only action cable still doesn't fully support falcon using http 2. But that's coming soon as well.


My assumption is that’s due to the use case benefits for it.

More concurrency is not always ideal, especially if you’re not in an environment that guarantees you won’t have negative impacts or runaways process (BEAM languages, etc).

Rails projects are typically so hardwired to use a background queue like Sidekiq that it becomes very natural to delegate most use cases to the queue.


> More concurrency is not always ideal

Is this due to increased memory usage? Does the same apply to Sidekiq if it was powered by Fibers?


Really depends on the job. But generally, yes the same applies to Sidekiq. I think there is a queue for Ruby called Sneakers that uses Fibers?

If you're making API calls out to external systems, you can use all of the concurrency that you want because the outside systems are doing all of the work.

If you're making queries to your database, depending on the efficiency of the query you could stress your database without any real benefit to improve the overall response time.

If you're doing memory intensive work on the same system then it can create a potential issue for the server and garbage collection.

If you're doing CPU intensive work, you risk starving other concurrent processes from using the CPU (infinite loops, etc).

Something like the BEAM is setup for this. Each process has it's own HEAP that's immediately reclaimed when the process ends without a global garbage collector. The BEAM scheduler actively intervenes switch which process is executing after a certain amount of CPU time, meaning that an infinite loop or other intensive process wouldn't negatively impact anything else...only itself. It's one of the reasons it typically doesn't perform as well in a straight line benchmark too.

Even on the BEAM you still have to be cautious of stressing the DB, but really you have to worry about that no matter what type of system you're on.


But wouldn't using a connection pool solve this problem of "stressing out the database"? I assumed a single connection from the pool would be considered "occupied" until we hear back from the database.

Or are you saying that processing lots of requests/tasks in Rails while waiting for the database would quickly eat up all the CPU? It seems like a good thing - "resource utilization" = servers should do things whenever possible rather than just waiting. Although now that I think about it you'd only want maximum resource utilization if your database is on a separate server.


With the database it depends on specific queries. Ideally, you can hammer it and it will be fine.

If you have inefficient queries, N+1 problems, competing locks, full table scans, temp tables being generated, etc then more concurrency will amplify the problem. Thats all I meant.




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: