Memory-lean nginx on a VPS

May 8, 2007

I spent this weekend testing and installing nginx and I have said Adios to Apache! Let me tell you why I have done that.

I am running this blog on a slicehost.com 256Mb Xen VPS, using WordPress. I have been using Apache 2.2 for almost a year now without any problems. But recently I deployed a little Ruby on Rails application using mongrel for my wife's business, and then suddenly I ran out of memory. Each Apache worker was easily taking 15 to 20Mb, even with a really cut-down configuration and built on Gentoo. With three Mongrel backends and the MySQL server I was starting to swap to disk.

I tried FastCGI instead of Mongrel, but it only cut down from about 50Mb to 40Mb for each process, not enough really to make a difference. I had to trim the fat out of the web server.

So about dropping Apache. First I considered Pound as a load balancer, but given that I would also still need a web server for static content in Rails (not wanting to serve that with Mongrel) I decided to look for alternatives.

Lighty and FastCGI tests did not even complete, so I gave up on Lighty. The FastCGI processes were becoming Zombie for some unknown reason.

Then I tried nginx. I have 5 workers, each consuming around 3Mb. Wow ... I call that Spring savings.

nginx is sending all blog traffic to a couple of php-cgi handlers. I tried both TCP and Unix sockets, but went for TCP since I was getting dropped requests and stalling processes for Unix sockets. php-cgi is not very fast, but it's stable and it has a reduced memory footprint.

Then nginx is acting as a reverse proxy and balancing across 3 Mongrels. I tried also FastCGI, but again it's not stable.

And man is this thing flying or what!? I have enough memory spare to make MySQL happy. Plus I am caching a lot of Rails generated content that nginx serves happily.

Now, some numbers from Apache Benchmark (running on Linux 2.6.16.29-xen #3 SMP, x86_64 Dual Core AMD Opteron(tm) Processor 265 AuthenticAMD GNU/Linux, Xen host with 256Mb):
nginx + pure HTML content:


Concurrency Level: 50
Time taken for tests: 0.96657 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Requests per second: 10345.86 [#/sec] (mean)
Time per request: 4.833 [ms] (mean)
Time per request: 0.097 [ms] (mean, across all concurrent requests)

nginx + php Wordpress home page (not cached, no APC):

Concurrency Level: 50
Time taken for tests: 192.387414 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Requests per second: 5.20 [#/sec] (mean)
Time per request: 9619.371 [ms] (mean)
Time per request: 192.387 [ms] (mean, across all concurrent requests)

nginx + mongrel (not cached):

Concurrency Level: 50
Time taken for tests: 8.290116 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Requests per second: 120.63 [#/sec] (mean)
Time per request: 414.506 [ms] (mean)
Time per request: 8.290 [ms] (mean, across all concurrent requests)

Sure, it's not a scientific test by any means, but it tells you something. And so far, no complains. If I ever outgrow the server, I can always get Pound on front of a couple of nginx web servers.


blog comments powered by Disqus