6 ms·
Can you really blame Ruby when the project didn't have the right resources? The team could have booted up more processes. Isn't that the answer? Or have I mis
by ketamine__ 6y ago
Can you really blame Ruby when the project didn't have the right resources?
The team could have booted up more processes. Isn't that the answer?
Or have I misinterpreted your comment?
- Railsify 6y agoThis is the right answer. The demo failed because the dev team failed to understand the performance and scaling characteristics of the code they wrote. This was a failure of people, not technology.
- josephg 6y agoEh - it was a failure of the (people, technology) tuple. Different choices by the engineers on the team could have fixed that problem. And different technology choices by the engineers behind ruby (/rails) could also have fixed the problem. (Eg async io, much larger thread pools, etc). Everyone dropped the concurrency ball hoping that was someone else's problem. Its the dev team's fault because everything is ultimately the dev team's fault. But it would also be great if it was fixed in ruby + ruby's ecosystem.
- Railsify 6y agoIf something is a known-known, you have to take personal responsibility when you don't take that thing into account and get bit. It's not appropriate to even mention some person you have not met as part of the reason a demo failed. Personal accountability it key in this industry, do your due diligence and events like were described will not happen.
- dwrowe 6y agoEasier to blame the seemingly nameless technology and completely change the conversation by using some other stack entirely that accounted for your lack of due diligence.
- sanderjd 6y agoYes but the point is that lots of people became disenchanted with ruby because it was notably harder to get this sort of thing right than it was for the alternatives with more built in support for in-process concurrency. Maybe it's not the case anymore, but back around 2010, the only people who knew what they needed to do to configure a rails app to scale decently were those who had battle scars of the kind in the parent comment. And nobody came out of those battles feeling all sunshine-and-roses about the platform.
- jashmatthews 6y agoRuby had support for in-process concurrency via threads for the last 14 years.
- sanderjd 6y agoAnd yet, see the comment that started this thread. It is simply true that concurrency was a pain point for rails for a lot of people for a long time. (I don't know if it still is, I've been out of that game for five years.)
- ReactiveJelly 6y agoBy resources do you mean hardware resources or expertise or what? Cause running more than 2 processes on a 2-core server just sounds weird. I thought Node's doctrine was "One process per core", and (async) Rust and Go seem to do fine with managing their own thread pools. I haven't _tried_ to do a realistic benchmark of Hyper, but I've never seen it struggle with concurrency either, even on long-polling applications where concurrency was the norm for all clients. More processes would work, but it doesn't seem like the right layer of abstraction for 2015, now that Nginx and Node have made the event model so popular.
- ketamine__ 6y agoMore hardware resources. The example given was a Rails app. I don't think one process per core is common for Rails deployments but I'm not sure.
- jashmatthews 6y agoProcess per core with threading for parallel IO has been the default for almost a decade now.
- ketamine__ 6y agoDefault in what app servers?
- jashmatthews 6y agoPuma is part of the default Rails Gems and was first released all the way back in 2011.
- strken 6y agoYou're absolutely right! The biggest things I learnt from that were: - overprovision resources for big demos by a significant amount - test your demo before you give it - deploying pets (servers you ssh into and lovingly configure) instead of cattle (instance abc123 that's created automatically) means you can't scale them as easily - if you have concerns about a big demo, particularly ones that could be fixed by spending $10 on EC2 instances, you should fix them yourself instead of emailing the tech lead and assuming he'll handle it - spinning up processes with phusion passenger is awful[0] and we should have been using something threaded like puma That being said, the same footguns apply at various points as you scale, because Ruby's GVL still exists, and because even though threads are lighter weight than processes, they're still relatively expensive to switch between and to maintain in memory compared to e.g. Go/Elixir lightweight threads or evented IO. Unfortunately (or perhaps fortunately) the problems with threaded IO start applying well above 20 concurrent users, so I don't have any fun stories about failed demos involving Puma instead of Passenger. [0] Specifically, Rails processes take up a lot of memory, none of it is shared, context switching between processes is pretty expensive, and so you're limited to a smaller number of processes that can become IO-bound very easily
- ketamine__ 6y agoPassenger can be configured to restart processes after they reach a memory threshold. Another optimization is using jemalloc. Going to try this soon with Sidekiq workers.
- jashmatthews 6y ago> Threads are lighter weight than processes they're still relatively expensive to switch between and to maintain in memory ... context switching between processes is pretty expensive This is a really common misconception. Both switching between threads and processes is _extremely_ fast compared to what web applications do. An exceptionally fast web response is generally <1ms. Linux thread context switching takes ~2 microseconds. Forking a new processes takes ~20 microseconds.
- strken 6y agoRelatively expensive was probably not phrased well, but a goroutine context switch is ~200 nanoseconds and instantiating a new one takes ~1 microsecond, from memory and a quick google.
- chmod775 6y agoI think you have missed where he said it had 20 people using it. Not 200,000. A single process wasn't able to handle 20. You'll be hard pressed intentionally writing code that performs that slowly in a framework in another language. Ruby by default has an incredibly long list of "you can but you shouldn't" and things you need to be aware of, especially around concurrency. Other languages are mostly fast by default. When you follow some nodejs/express/whatever introduction tutorial and implement your first application in the most naive way possible, you'll end up with something that will easily scale to hundreds if not thousands of users out of the box. Do the same with ruby (or even with some python frameworks, to be fair), and stuff can break at less than a hundred users. And that's why yes, you can blame that on ruby. Or at least ruby how it is commonly taught.
- ketamine__ 6y agoThere is a lot we don't know with the example given. It's unfair to blame Ruby.
- lostcolony 6y agoBut it's not unique to this example. It's common; if you don't start out concerned about concurrency in Ruby, and just do the naive thing, you are going to fall over at -extremely- low numbers compared with most other modern languages.
- debaserab2 6y agoThe "naive" thing in Ruby, if you're serving HTTP requests, is to use some kind of app gateway that allows concurrency, such as puma or unicorn. It's just not all that viable to do something more basic than that unless you're willing to write all the request handling stuff by hand. That aside, a ruby script that can't handle 20 req/s on 2 vcpus seems rather suspect. I'd be really curious what that code looked like. I'm doubtful that it has much to do with the language and not the code design.
- the-dude 6y agoIf it is so common as you claim, could you point us to some public examples of this? I have never ever been concerned about concurrency in Ruby, or Python or PHP. Just deployed the number of workers which would be able to serve our peaks. I do write high concurrency application though, but those are not web apps and are not written in these languages.