I agree with you, with a caveat. I think that the model is better for some specific use cases.
_ry and I had this debate at reasonable length back before node, when he was writing flow and I prepped the first thin async patch/rack hack.
The fundamental problem here is a competition of use cases and ideals. It would be ideal for server authors if Ruby had lightweight coroutines that could be scheduled across threads and relinquish control on IO. You can emulate some of this with Fibers, and Neverblock went really far down this path, as did Goliath. There's really no substitute for real user schedulable goroutines and a decent IO subsystem though - we can build the latter, but the prior is squarely in MRI's control - and they're now headed further down the path of thread isolation.
Skipping a very large background and diatribe of these choices in MRI, I will say that the chosen path is really not suitable for very high scale processes. To be clear, I'm not saying "ruby doesn't scale" in the sense that we can't use it for services that handle Mqps and up. You can - it's not cheap, but it's entirely doable, and the engineering cost is on par with other choices, assuming reasonable problem solving. What I am saying is that Ruby, as designed and where it is headed, will not be ideal for tens of thousands of open sockets, or more. It does not have enough lightweight datastructures. It doesn't have the right IO primitives, and it doesn't have the right concurrency primitives. The newer concurrency primitives that are being discussed also make solving the general case of this problem harder. The general case assumes that task latencies are unpredictable, and in that space, you need a scheduler that can perform memory and cpu offloading. MRI will not deliver either of those capabilities.
The reason I describe the above, is that if we accept that Ruby is only good for limited scale and cost per process, then we can view the problem a little differently. Instead of trying to force it, or constantly work around those limitations in library level systems, we can work around the problem in flow control and traffic management systems. Indeed this is what we do today, though as you note, often by accident/side effect. The kinds of catastrophic load balancing challenges such as the rap genius saga will remain, and slow client challenges will also. We can deal with them. At scale you never really get to escape these anyway, except by engineering systems to specifically combat those challenges. Either you're so fast and efficient that attacks are impractical, or you start needing to put appropriate limitations in place in upstream defenses. Ultimately the prior is brittle and as such the latter eventually gets deployed by SRE/sysadmins/ops folks.
I also don't mean to say that it would be bad to explore some more of these ideas. I think it would, particularly if it could lead to more examples of what servers need in order to be efficient, as strong cases for MRI/Ruby designers to consider. I also think there are good cases to be made for alternative servers for specific use cases - I know you specifically Eric have done great work in this area. I would encourage you, absolutely, to freely depart from Rack for those use cases. I'd also be really happy to eat my words if you find some way of taking on elixir style scalability with MRI, though on a personal level I don't know if it's worth the time. As always, thank you for everything you've done, and for the discussion.
--
---
You received this message because you are subscribed to the Google Groups "Rack Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rack-devel+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Thank you for your response.
As far as departing from Rack... I guess PSGI was one departure :)
Looking back, I think the possibility of an ecosystem of
stdlib/gems to support lightweight coroutines was lost when MRI
got 1:1 threads with YARV. Fibers, Neverblock, Goliath never
got the critical mass to affect stdlib or most gems after that.
So yeah, I agree this really needs core/stdlib support which I
doubt can still happen. Coro for Perl5 is in a bad, perhaps
worse spot, even.
And yet I know my brain still favors OS kernel primitives over
language-level primitives; so in that way MRI/YARV today is
closer to how my brain works w.r.t. non-blocking I/O combined
with native threads or processes as needed. *shrug*
Yet, it seems the Ruby mainstream is content with primitive
servers like unicorn. I often wonder if the unintentional
popularity of unicorn set the Ruby ecosystem back 5-10 years in
terms of concurrency. Likely so, but the damage is done :<
In my defense, I suck at marketing, so it's not my fault.
Anyways, my original post was really a reporting-in-from-hiatus
message. I haven't done anything new with server design in over
5 years, and don't expect I will in the future; just occasional
janitorial work. yahns was merely a repackaging and
consolidation of findings from Rainbows! as a "best of" release
with some warts removed.