Ask HN: On scalability and memory footprint
One of my co-workers is constantly arguing with me that we should not worry about memory footprint. For instance, let Rails use as much memory as it wants, the reasoning being that it would be pointless to try and cut down memory usage since we can just expand to as many slices with as much memory as we need on EC2.
Now, is there a significant speed increase in trying to keep memory usage low? What would be the educated answer for this? I could surely try to argue that yes using my programming knowledge and practice only, but I think a truly informed answer would require a deeper understanding of things.
(
19 comments
| 13 points
| on HN
)
Sure, throwing more ec2 instances at the problem is one solution, but if you care about your apps performance you will try to optimize for smaller memory footprint.
That said, watch your 'n's. If you scale linearly, you can keep throwing servers at the problem. If you end up with some critical piece of your code that's, say, quadratic in run-time or memory consumption, you can't. And when you get there: profile, don't guess. Monte-Carlo code optimization is the beginning of the end for an otherwise clean code-base.
Good design lets your site stay lean and mean.
Sure, we could process the data rows outside of Rails in C but because the processing of data rows is an integral part of the project, that would mean coding 80% in C and 20% in rails. Not exactly an enjoyable experience.
So we rewrote it in PHP and avoid objects and use just functions and hashes/arrays. And it worked very well for us. The site render time drops from 0.8s to 0.03s. Memory usage rarely exceeds 100MB.
I'm already rewriting the API code in a minimal Merb app, which uses a lot fewer memory and can-haz C-based ORM code with DataMapper. My plan in the future is to try and push possible migration of the Rails-based site code to Merb as well.
Premature optimization? Avoid it. Writing good code? Don't avoid it because bad code is easier and memory is cheap. There are some times when it makes no logical sense to allow something to use tons of memory, despite how much you have available. For instance, if you request the same page from your site over and over again and the memory usage continues to increase, that's probably a bad thing. What is that process storing in local memory and not garbage-collecting after a request? It's HTTP so there should be no persistence at the web framework level (i.e. in Rails). It should manufacture a request, send it, and move on to the next one, shedding all the local variables made in the process. If your memory footprint is increasing while your real load is remaining the same, that's bad. If you're storing the same object in memory in 5 different places, that's bad -- but not that big a deal so long as they're all gone when the request has been served.
(Flamebait P.S. -- save memory, kill Rails.)
2) Go back and refactor the things that really stick out as bulky
3) Deploy
4) Continue your release cycles and refactor stuff as you come across them
.
As the saying goes — hardware is cheap, your time isn't.
Don' t many small companies find that they have more time than money?
I think if your a small company you shouldn't be worrying about small issues like this, even if you have more time than money. It may be making your app more efficient, but your doing it the same way people make apps bulky and never get them out the door! Spend the time on things which truly matter, and fix slightly slower code when its beginning to cause a problem. :)
When the app is written, if you run a load test (or you can let your users be your load test, like Twitter), there will be a bottleneck for some n of users. Remove this bottleneck, which could be cpu, database, memory, connections, bandwidth, etc., and there will be a new bottleneck at some > n users. Rinse, lather, repeat.
If you optimize now, you're most certainly optimizing the wrong thing. When I load tested my first production rails app, I found cpu was the first bottleneck I hit, not memory.
To keep memory usage low, I find recycling mongrel processes via monit can help a bunch.
Before monit, my mongrels would hit 2GB quickly, after monit with a rule to restart when they hit over 100MB, my memory usage is around 800MB for 15 mongrels. (I'm assuming you are using HAProxy or a similar balancer that can deal with changes of availability).
http://userscripts.org/articles/2-scaling-a-rails-site
Another useful tip is make sure your queries aren't doing stupid stuff. A long time ago I had integrated Beast (a rails forum project) into my site. Unfortunately it was loading EVERY topic on the forum index page, which was resulting in slowness as well as large jumps in memory usage. (The culprit was a .last method that caused all the records to load and then grab the last value)
So - I tend to agree with "don't worry" because you can "patch" over memory usage pretty easily.
My site is currently getting 17req/s on a single box - it is never what you think will be the issue that you have to fix.
If, like furiouslol, you're trying to access a 2-3 million row table and Active Record is topping out at 2GB of RAM and taking close to 1 second on a production machine just to render a page, then yes, you might need to worry about memory usage.
But, if you're prototyping a site, and just getting it off the ground, I would worry about memory usage later.
If you're really freaked out about performance, you can always try PHP or Django. They tend to be a bit more sparing on system resources.
If you're serious about this, build your test cases, and benchmark.
But before you invest here, ensure you have nothing better to do with your time, and ensure that the probable payback can be justified against the aggregate investment; against the costs of the testing and of the migration. And nothing better to debate, for that matter.