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.
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.
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.
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!
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.
As someone who develops web apps for startups not in SV, that seems incredibly expensive to me.
Having said that, while I don't find any major reasons to opt for Phoenix instead of Rails, my main reason to work with Elixir/Phoenix right now on side projects is that it won't make me unlearn Rails which I can always go back to, in fact, using Phoenix for a while made me miss a lot of the available libraries, plug-in solutions and wide range of community knowledge.
So ATM I have more reasons to choose Rails over Phoenix, but I suppose that's why these sorts of articles are important, publicity to increase a community and fulfill Elixir's biggest need right now.
This is my main reason for focusing on Rails rather than Elixir at present. The sheer breadth of gems available for rails to quickly build sophisticated applications is hard to beat for any up and coming language/framework.
That said, my gut feel is that many of the developers who build and maintain these gems have moved on and that Elixir is the new hotness and will probably catch up in the next few years.
The second problem is importing a huge chunk of rows at once means they have to exist in RAM at the same time. Use batched iterators to reduce peak memory usage. All GCed languages have this problem, Go included.
You'd think Go's GC was somehow revolutionary from the way they talk about it, but it's basically the same as the Ruby GC, plus a little more parallelism. What helps Go is that the compiler can optimise and use stack allocation and re-use temprory variables. If it fails, it causes a nightmare, and the Go standard library is full of tricks to convince the compiler to do stack allocation.
Java, OTOH, has compacting garbace collection, so after high peak memory usage, it can release the memory back to the OS. Aaron Patterson has been working on doing the same for Ruby. If you use JRuby, you'll get this right now, plus it's about 3x faster for shuffling data around.
Java doesn't, or at least didn't, collect anonymous classes without an additional GC flag being enabled, which could bite you quite hard using JRuby with gems which made heavy use of anonymous classes.
I'm not sure if these same problems do or don't come up with Phoenix, but when I briefly used it, it did seem to have a smaller memory footprint.
Yes, gems. The ecosphere in ruby is superb. I'm started working with node a lot more these days and it's a) confusing and b) small packages for all those things whatevertheycallitthesedaysscript is missing. 243 gems in my 7yr old Ruby vs 918 node modules in an app we started this month. What's Elexir/Erlang like in this respect?
Also, we do about 99 writes for every 1 read, so query times don't matter as much. For the given app I was using as an example.
Network I/O and large databases are usually the bottlenecks from what I've seen consulting and developing.
Those are pretty awful numbers. https://blog.gigaspaces.com/amazon-found-every-100ms-of-late...
The thing is, I've always scaled my website(s) to thousands or tens of thousands of requests and hour; with one website even getting close to a million an hour... all with no problem. In the case of Rails (as is discussed in the article), my bottleneck (from a usability perspective) is always bandwidth. Most applications (I build anyway), require a hefty amount of data. Waiting 200ms for the database + an additional 20ms for rendering, the 20ms is not noticeable. Scaling Rails (or any modern web app) is as easy as just launching another instance and load balancing.
Given that, I really don't see any advantage toward Phoenix. Plus, why I personally love rails is all the gems - which is super powerful. Most other frameworks simply don't have Rails simple logic, with the easily extendable gems.
[1] http://austingwalters.com/building-a-web-server-in-go-handli...