Benchmarking Rails enabled Web Servers
Following the article Running Rails applications: Choosing a server where I compared the different combinations server/dispatcher available for Rails, I have done a small benchmark to see what server actually performs better.
The servers I have tested are: Apache2 + Dynamic mod_fastcgi, Apache2 + mod_fcgid, Apache + Static mod_fastcgi and Lighttpd 1.4 + mod_fastcgi. The benchmark was performed using ab (Apache Benchmark), in a machine in the same LAN as the server (an old Pentium-4 with 512Mb of RAM), running first 100 requests with a concurrency level of 10 (ab -c 10 -n 100), and then, 500 requests with a concurrency level of 50 (ab -c 50 -n 100).
Configuration used:
Apache2 + Dynamic mod_fastcgi:
Apache2 + mod_fcgid:
Apache2 + Static mod_fastcgi
Lighttpd + mod_fastcgi
Apache 2.2 + Dynamic mod_fastcgi (min-processes 2)
100 requests; Concurrency level: 10
500 requests; Concurrency level: 50
Apache 2.2 + mod_fcgid
100 requests; Concurrency level: 10
500 requests; Concurrency level: 50
Apache 2.2 + Static mod_fastcgi (processes 4)
100 requests; Concurrency level: 10
500 requests; Concurrency level: 50
Lighttpd 1.4 + mod_fastcgi (min-procs 2; max-procs 4)
100 requests; Concurrency level: 10
500 requests; Concurrency level: 50
Conclusion
The servers I have tested are: Apache2 + Dynamic mod_fastcgi, Apache2 + mod_fcgid, Apache + Static mod_fastcgi and Lighttpd 1.4 + mod_fastcgi. The benchmark was performed using ab (Apache Benchmark), in a machine in the same LAN as the server (an old Pentium-4 with 512Mb of RAM), running first 100 requests with a concurrency level of 10 (ab -c 10 -n 100), and then, 500 requests with a concurrency level of 50 (ab -c 50 -n 100).
Configuration used:
Apache2 + Dynamic mod_fastcgi:
<IfModule mod_fastcgi.c>
AddHandler fastcgi-script .fcgi
FastCgiConfig -minProcesses 2 -maxProcesses 4
</IfModule>
Apache2 + mod_fcgid:
<IfModule mod_fcgid.c>
AddHandler fcgid-script .fcgi
SocketPath /var/lib/apache2/fcgid/sock
IPCConnectTimeout 20
</IfModule>
Apache2 + Static mod_fastcgi
<IfModule mod_fastcgi.c>
AddHandler fastcgi-script .fcgi
FastCgiServer /path/to/dispatch.fcgi -processes 4
</IfModule>
Lighttpd + mod_fastcgi
server.modules += ( "mod_rewrite", "mod_redirect", "mod_fastcgi" )
fastcgi.server = (
#Start a FastCGI server for Rails
".fcgi" =>
( "rails" =>
(
"bin-path" => "/path/to/dispatch.fcgi",
"min-procs" => 2,
"max-procs" => 4,
"socket" => "/tmp/rails.fastcgi"
)
)
)
Apache 2.2 + Dynamic mod_fastcgi (min-processes 2)
100 requests; Concurrency level: 10
Document Length: 4558 bytes
Concurrency Level: 10
Time taken for tests: 13.951477 seconds
Complete requests: 100
Failed requests: 0
Write errors: 0
Total transferred: 488300 bytes
HTML transferred: 455800 bytes
Requests per second: 7.17 [#/sec] (mean)
Time per request: 1395.148 [ms] (mean)
Time per request: 139.515 [ms] (mean, across all concurrent requests)
Transfer rate: 34.12 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 2.1 0 10
Processing: 1139 1342 425.6 1182 3056
Waiting: 1139 1342 425.1 1181 3053
Total: 1139 1343 427.4 1182 3056
Percentage of the requests served within a certain time (ms)
50% 1182
66% 1262
75% 1281
80% 1286
90% 2006
95% 2683
98% 2962
99% 3056
100% 3056 (longest request)
500 requests; Concurrency level: 50
Document Length: 4558 bytes
Concurrency Level: 50
Time taken for tests: 73.904226 seconds
Complete requests: 500
Failed requests: 0
Write errors: 0
Total transferred: 2441500 bytes
HTML transferred: 2279000 bytes
Requests per second: 6.77 [#/sec] (mean)
Time per request: 7390.423 [ms] (mean)
Time per request: 147.808 [ms] (mean, across all concurrent requests)
Transfer rate: 32.26 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.6 0 2
Processing: 121 7142 4947.1 5644 25456
Waiting: 121 7142 4947.1 5644 25455
Total: 123 7142 4947.3 5644 25457
Percentage of the requests served within a certain time (ms)
50% 5644
66% 6027
75% 6468
80% 6615
90% 19164
95% 21813
98% 22193
99% 22493
100% 25457 (longest request)
Apache 2.2 + mod_fcgid
100 requests; Concurrency level: 10
Document Length: 4558 bytes
Concurrency Level: 10
Time taken for tests: 11.987351 seconds
Complete requests: 100
Failed requests: 0
Write errors: 0
Total transferred: 488800 bytes
HTML transferred: 455800 bytes
Requests per second: 8.34 [#/sec] (mean)
Time per request: 1198.735 [ms] (mean)
Time per request: 119.874 [ms] (mean, across all concurrent requests)
Transfer rate: 39.79 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 36 119.8 0 493
Processing: 179 1124 603.8 1048 3094
Waiting: 0 1115 610.1 1048 3094
Total: 198 1161 622.0 1048 3094
Percentage of the requests served within a certain time (ms)
50% 1048
66% 1280
75% 1652
80% 1731
90% 2082
95% 2506
98% 2663
99% 3094
100% 3094 (longest request)
500 requests; Concurrency level: 50
Document Length: 4558 bytes
Concurrency Level: 50
Time taken for tests: 77.213299 seconds
Complete requests: 500
Failed requests: 18
(Connect: 0, Length: 18, Exceptions: 0)
Write errors: 0
Non-2xx responses: 18
Total transferred: 2361938 bytes
HTML transferred: 2198180 bytes
Requests per second: 6.48 [#/sec] (mean)
Time per request: 7721.330 [ms] (mean)
Time per request: 154.427 [ms] (mean, across all concurrent requests)
Transfer rate: 29.87 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 98 317.2 0 1203
Processing: 140 6214 15936.0 950 76018
Waiting: 133 6210 15935.9 946 76017
Total: 140 6313 16175.8 973 77211
Percentage of the requests served within a certain time (ms)
50% 973
66% 1377
75% 1827
80% 1985
90% 20811
95% 61097
98% 63166
99% 70184
100% 77211 (longest request)
Apache 2.2 + Static mod_fastcgi (processes 4)
100 requests; Concurrency level: 10
Document Length: 4558 bytes
Concurrency Level: 10
Time taken for tests: 10.954809 seconds
Complete requests: 100
Failed requests: 0
Write errors: 0
Non-2xx responses: 100
Total transferred: 488300 bytes
HTML transferred: 455800 bytes
Requests per second: 9.13 [#/sec] (mean)
Time per request: 1095.481 [ms] (mean)
Time per request: 109.548 [ms] (mean, across all concurrent requests)
Transfer rate: 39.02 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 250 293.3 86 996
Processing: 85 809 845.6 679 6093
Waiting: 0 734 857.3 615 6092
Total: 422 1059 837.3 919 6093
Percentage of the requests served within a certain time (ms)
50% 919
66% 1039
75% 1039
80% 1081
90% 1172
95% 2755
98% 5405
99% 6093
100% 6093 (longest request)
500 requests; Concurrency level: 50
Document Length: 4558 bytes
Concurrency Level: 50
Time taken for tests: 60.694702 seconds
Complete requests: 500
Failed requests: 0
Write errors: 0
Total transferred: 2441500 bytes
HTML transferred: 2279000 bytes
Requests per second: 8.24 [#/sec] (mean)
Time per request: 6069.470 [ms] (mean)
Time per request: 121.389 [ms] (mean, across all concurrent requests)
Transfer rate: 39.28 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.6 0 2
Processing: 240 5789 1069.7 5993 7837
Waiting: 240 5789 1069.8 5993 7837
Total: 242 5789 1069.3 5993 7837
Percentage of the requests served within a certain time (ms)
50% 5993
66% 6129
75% 6231
80% 6277
90% 6400
95% 6508
98% 6678
99% 6972
100% 7837 (longest request)
Lighttpd 1.4 + mod_fastcgi (min-procs 2; max-procs 4)
100 requests; Concurrency level: 10
Server Software: lighttpd/1.4.13
Document Length: 4558 bytes
Concurrency Level: 10
Time taken for tests: 11.976793 seconds
Complete requests: 100
Failed requests: 0
Write errors: 0
Total transferred: 481100 bytes
HTML transferred: 455800 bytes
Requests per second: 8.35 [#/sec] (mean)
Time per request: 1197.679 [ms] (mean)
Time per request: 119.768 [ms] (mean, across all concurrent requests)
Transfer rate: 39.16 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.0 0 0
Processing: 183 1160 657.1 1020 2889
Waiting: 174 1040 670.8 874 2735
Total: 183 1160 657.1 1020 2889
Percentage of the requests served within a certain time (ms)
50% 1020
66% 1234
75% 1658
80% 1830
90% 2108
95% 2561
98% 2833
99% 2889
100% 2889 (longest request)
500 requests; Concurrency level: 50
Server Software: lighttpd/1.4.13
Document Length: 4558 bytes
Concurrency Level: 50
Time taken for tests: 62.138366 seconds
Complete requests: 500
Failed requests: 0
Write errors: 0
Total transferred: 2405500 bytes
HTML transferred: 2279000 bytes
Requests per second: 8.05 [#/sec] (mean)
Time per request: 6213.837 [ms] (mean)
Time per request: 124.277 [ms] (mean, across all concurrent requests)
Transfer rate: 37.80 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 170 547.2 0 2068
Processing: 105 5755 1372.4 6227 6909
Waiting: 5 5686 1383.7 6201 6682
Total: 2074 5926 955.5 6228 6928
Percentage of the requests served within a certain time (ms)
50% 6228
66% 6285
75% 6325
80% 6411
90% 6468
95% 6485
98% 6528
99% 6542
100% 6928 (longest request)
Conclusion
As we may already be expecting, the worst performer is Apache2 + Dynamic mod_fastcgi.
Apache2 + mod_fcgid is performing surprisingly bad with a lot of stress. However, the performance could probably be better changing some of the configuration parameters.
Either Apache 2 + Static mod_fastcgi or Lighttpd + mod_fastcgi is the way to go, the latter performing a little better. My recommendation: use Lighttpd whenever possible. If you need to use Apache2, set mod_fastcgi in static mode.
Apache2 + mod_fcgid is performing surprisingly bad with a lot of stress. However, the performance could probably be better changing some of the configuration parameters.
Either Apache 2 + Static mod_fastcgi or Lighttpd + mod_fastcgi is the way to go, the latter performing a little better. My recommendation: use Lighttpd whenever possible. If you need to use Apache2, set mod_fastcgi in static mode.

