4 ms·
I mean... 1 million requests an hour isn't that many. That's around 300 requests per second. Assuming 1000ms upper bound on requests, you need 300 workers to h
by phamilton 9y ago
I mean... 1 million requests an hour isn't that many.
That's around 300 requests per second. Assuming 1000ms upper bound on requests, you need 300 workers to handle that load. Assuming 150MB per worker, that's 45 GB of memory required to handle the load. So like... 5 m4.xlarge instances on EC2 (to give redundancy and allow loss of 2 hosts). That's $700/month.
That's not that much. We've got a Rails app that pushes 5000 qps. And to be fair, we just dial up the number of instances and it handles it fine. It runs on over 100 instances. It costs us around $10k/month. Not the end of the world, cost wise, but we have multiple Go services that handle similar levels of traffic and run on a dozen instances. Additionally, deploys take a long time (rolling restarts plus health checks on 100 machines takes time).
Moving to Go (or Elixir) allows us to handle far more requests per unit of hardware. While latency would indeed improve, it's not the primary motivator for us moving away from Rails.
I haven't even mentioned the websocket story on Rails. That's a whole new can of worms.
- meritt 9y agoDo rails apps actually use 150MB per worker or was that just a lofty ceiling estimate? Or is that with an app server that doesn't utilize process forking, and loses the benefit of shared libraries/heap/etc?
- gkop 9y agoYes, they often do :/
- tychver 9y agoYes, but you only need one process per core, just like NodeJS. Since 1.9 you can use real OS threads to achieve parallel IO, and certain parallel computations which can proceed without holding the Global Interpreter Lock. JRuby offers completely unrestricted threading with a single process, plus a 3x performance boost, plus the advantage of an incredible amount of work put into their VM and GC. It's a really underrated option these days. The problem with forking, is MRI Ruby is unaware what memory is actually inherited by forking, so eventually it causes the entire heap inherited from the parent to copy into the child. I'm actually working on a patch to fix this. The solution is simple, just don't mark, collect, or allocate into inherited pages, but the implementation itself is fiddly. What's really exacerbated this, is that most Linux distros now have Transparent Huge Pages turned on by default, and flipping a single bit in inherited causes a 2MB copy instead of a 4kb copy!
- Rapzid 9y agoI'm fairly certain this was fixed in 2.0? https://medium.com/@rcdexta/whats-the-deal-with-ruby-gc-and-copy-on-write-f5eddef21485 https://medium.com/@rcdexta/whats-the-deal-with-ruby-gc-and-...
- tychver 9y agoNah, unfortunately simply moving the GC bits from the object itself to bitmap in the page header made Ruby CoW friendlier but not CoW friendly! Each Ruby page is 4x OS pages on Linux, so marking into the header of each Ruby page still causes 1/4 of the parent heap to copy into the child process. The bigger issue is heap fragmentation. Lots of inherited pages have a couple of free slots that Ruby will happily consume, effectively causing you to pay a 4kb copy for a 40 byte object. This means allocating a few hundred objects can cause basically the entire heap to copy. Combine this with Transparent Huge Pages, where flipping one bit causes a 2MB copy rather than 4kb, and a few hundred object allocations can cause the entire parent process memory to be duplicated into the child. Aaron Patterson is doing some great work to bring GC compaction to MRI, which will help reduce fragmentation, but it's a huge task.
- dvdhnt 9y ago> It costs us around $10k/month. As someone who develops web apps for startups not in SV, that seems incredibly expensive to me.
- michaelbuckbee 9y agoWell, it's a sliding scale isn't it? If you have less traffic/paying customers you can pull that back down.
- phamilton 9y agoIt's the difference between 30 developers and 31 developers on payroll.
- WillPostForFood 9y ago* 1 million requests an hour isn't that many.* What percentage of websites serve 1 mil or more requests per hour, .01%? .001%? Meaning Rails is going to be performant enough for 99.9+% of projects, and for those projects it would have been a mistake to trade dev time for performance you’ll never need.
- deleted 9y ago[deleted]
- phamilton 9y ago1M request per hour at peak? A SPA backed by rails is probably going to make at least 10 requests on page load. So in terms of actual traffic, 100k page loads during a peak hour. Assume a roughly linear peak increase/decrease and we've got roughly 1M page loads per day. 30M page loads per month. How many websites have 30M (non-unique) page loads per month? After some rough scouting on Alexa ranks, I'd put the over-under at probably 10k US sites, and 50k worldwide. Assuming Alexa has 50M sites, then 0.1% of publicly facing sites serve that much traffic. Rails is used often on private, internal sites and tooling. Those sites wouldn't come up. That would definitely skew the 0.1% number. Not making a huge argument here, I just started down that analysis path out of curiosity and figured I'd share it.
- WillPostForFood 9y agoGreat analysis! According to Netcraft, there are > 600million websites, so assuming Alexa ignores the 550 million with near zero traffic, you can get to the .01% pretty easily. Another area I'd tweak is the skew towards SPAs. Most sites aren't SPAs, especially as you slide down the traffic rankings.
- phamilton 9y agoYeah, the skew towards SPA is more Rails focused. I haven't worked on a non SPA Rails app in over 5 years. P(SPA | Rails) is higher than P(SPA).
- nurettin 9y agoHave you ever considered JRuby on Rails? We've had 10.000 students choosing lectures online at the same time using torquebox back in 2012 on just two server instances with multimaster replicated MySQL.