Re: problems with fastcgi performance & ruby
"Zev Blut" <[email protected]>
| Newsgroups | gmane.comp.web.fastcgi.devel |
|---|---|
| Message-ID | <[email protected]> |
Hello, On Tue, 2 Nov 2004 14:11:05 +1100, Andrew Stuart <[email protected]> wrote: > It is all working a running but the performance is not what I had > expected > and certainly not what is needed to run a production web application. What are you expecting? Are you trying to optimize for throughput or latency? From you tests below I am guessing throughput. What are your metrics for a "production web application"? Which costs more developer time or hardware? If developer time is more valuable you can always buy more hardware and load balance it for increased throughput. Here are a few points with regards to your tests: 1) The scripts you are trying to compare against are not all the same. For example your env Ruby scripts are still more complex than your PHP script. If you want meaningful data you should try to test with programs that are generating the same result (or as much as possible when it comes to echoing the environment). You should probably just start with benchmarking echo. Note: Your echo scripts are not the same either. The example c echo script does not sort the environment. So you should not sort the environment in your Ruby script either. I have provided two Ruby scripts below that are a little bit closer to matching the C example. 2) Below is your Apache configuration of mod_fastcgi: > LoadModule fastcgi_module modules/mod_fastcgi.so > > <IfModule mod_fastcgi.c> > > # URIs that begin with /fcgi-bin/, are found in /var/www/fcgi-bin/ > Alias /fcgi-bin/ /var/www/fcgi-bin/ > > FastCgiIpcDir /var/fcgi/ > #FastCgiConfig -autoUpdate > > # Anything in here is handled as a "dynamic" server if not defined as > "static" or "external" > <Directory /var/www/fcgi-bin/> > Order allow,deny > Allow from all > SetHandler fastcgi-script > Options +ExecCGI > #Require user andrewstuart > </Directory> > > # Anything with one of these extensions is handled as a "dynamic" > server > if not defined as > # "static" or "external". Note: "dynamic" servers require ExecCGI to > be > on in their directory. > AddHandler fastcgi-script .fcgi .fpl > > # Start a "static" server at httpd initialization inside the scope of > the SetHandler > FastCgiServer /var/www/fcgi-bin/examples/echo -processes 5 > > # Start a "static" server at httpd initialization inside the scope of > the AddHandler > #FastCgiServer /var/www/fcgi-bin/examples/echo > > # Start a "static" server at httpd initialization outside the scope > of > the Set/AddHandler > #FastCgiServer /var/www/htdocs/some/path/coolapp > <Directory /var/www/html/ruby> > SetHandler fastcgi-script > </Directory> > > </IfModule> Notice that FCGI c echo example is is set to start with 5 processes from the beginning. Try making all of your test scripts match that statement. For example: FastCgiServer /var/www/htdocs/some/path/coolapp/ruby_echo.rb -processes 5 As you are attempting to do 100 parallel requests, you may want to play with increasing the processes number to see if that helps improve throughput. 3) Below are sample runs from my development machine: Dual Processor Pentium III 750 MHz Redhat 9 Apache 2 FCGI 2.4.0 mod_fcgi 2.4.0 Ruby 1.8.2 (2004-05-24) [i686-linux] ############################################################ # with both apps set to 5 processes ############################################################ # Ruby echo # Note: I did not include the standard input check, as I am not # exactly sure how I would simulate this. # Plus the Initial environment is the same output either. # But it is closer to what the c version does. ------------------------------------------------------------ #!/usr/local/bin/ruby require 'cgi' require 'fcgi' def print_env(title,env) str = "#{title}:<br>\n<pre>\n" env.each do |k,v| str<<"#{k}=#{v}\n" end str<< "</pre><p>\n" end count = 0 FCGI.each_cgi do |cgi| count += 1 content = "<title>FastCGI echo</title><h1>FastCGI echo</h1>\n" content<< sprintf("Request number %d, Process ID: %d<p>\n", count, Process.pid) content<< print_env("Request environment", cgi.env_table) content<< print_env("Initial environment", ENV) # not sure if that is what is intended for the c impl. cgi.out{content} end ------------------------------------------------------------ ############################################################# ***** Ruby Version ***** $ ./http_load -parallel 100 -seconds 20 ruby_url.txt 2> /dev/null 9031 fetches, 100 max parallel, 8.05197e+06 bytes, in 20.0063 seconds 891.592 mean bytes/connection 451.408 fetches/sec, 402472 bytes/sec msecs/connect: 3.05451 mean, 164.012 max, 0.104 min msecs/first-response: 125.278 mean, 743.138 max, 6.421 min 5345 bad byte counts HTTP response codes: code 200 -- 9031 ***** C Version ***** ./http_load -parallel 100 -seconds 20 c_url.txt 2> /dev/null 16177 fetches, 100 max parallel, 1.6673e+07 bytes, in 20.0104 seconds 1030.66 mean bytes/connection 808.431 fetches/sec, 833216 bytes/sec msecs/connect: 2.21553 mean, 75.915 max, 0.095 min msecs/first-response: 55.6049 mean, 488.322 max, 4.388 min 16134 bad byte counts HTTP response codes: code 200 -- 16177 ############################################################ # without setting the processes ############################################################ ***** Ruby Version ***** $ ./http_load -parallel 100 -seconds 20 ruby_url.txt 2> /dev/null 6706 fetches, 100 max parallel, 5.98064e+06 bytes, in 20.0051 seconds 891.835 mean bytes/connection 335.214 fetches/sec, 298956 bytes/sec msecs/connect: 0.970607 mean, 73.495 max, 0.115 min msecs/first-response: 294.584 mean, 524.954 max, 80.764 min 6697 bad byte counts HTTP response codes: code 200 -- 6706 ***** C Version ***** $ ./http_load -parallel 100 -seconds 20 c_url.txt 2> /dev/null 12016 fetches, 100 max parallel, 1.23894e+07 bytes, in 20.0001 seconds 1031.08 mean bytes/connection 600.798 fetches/sec, 619468 bytes/sec msecs/connect: 1.25415 mean, 151.896 max, 0.113 min msecs/first-response: 159.242 mean, 550.63 max, 10.673 min 12007 bad byte counts HTTP response codes: code 200 -- 12016 ############################################################ # Ruby with 20 processes ############################################################ $ ./http_load -parallel 100 -seconds 20 ruby_url.txt 2> /dev/null 8649 fetches, 100 max parallel, 7.70597e+06 bytes, in 20.0581 seconds 890.967 mean bytes/connection 431.198 fetches/sec, 384183 bytes/sec msecs/connect: 3.0964 mean, 126.724 max, 0.108 min msecs/first-response: 133.628 mean, 1024.41 max, 4.549 min 8470 bad byte counts HTTP response codes: code 200 -- 8649 ############################################################ # Below is another implementation of echo in Ruby, this time # without creating a cgi instance. # This shows that if performance is a critical issue you will need to # watch what you create. ------------------------------------------------------------ #!/usr/local/bin/ruby require "fcgi" def print_env(title,env) str = "#{title}:<br>\n<pre>\n" env.each do |k,v| str<<"#{k}=#{v}\n" end str<< "</pre><p>\n" end count = 0 FCGI.each do |request| count +=1 out = request.out content = "<title>FastCGI echo</title><h1>FastCGI echo</h1>\n" content<< sprintf("Request number %d, Process ID: %d<p>\n", count, Process.pid) content<< print_env("Request environment", request.env) # not sure if that is what is intended for the c impl. In this example ENV is empty. content<< print_env("Initial environment", ENV) out.print "Content-Type: text/html\r\n" out.print "Content-Length: #{content.size}\r\n" out.print "\r\n" out.print content request.finish end ------------------------------------------------------------ ############################################################ $ ./http_load -parallel 100 -seconds 20 n_ruby_url.txt 2> /dev/null 12172 fetches, 100 max parallel, 1.12779e+07 bytes, in 20.0209 seconds 926.546 mean bytes/connection 607.966 fetches/sec, 563308 bytes/sec msecs/connect: 2.46843 mean, 135.91 max, 0.097 min msecs/first-response: 98.272 mean, 443.003 max, 2.215 min 12130 bad byte counts HTTP response codes: code 200 -- 12172 ############################################################ Quick Summary: 5 Processes Ruby 451.408 fetches/sec No CGI Object Ruby 5 Processes 607.966 fetches/sec 5 Processes C 808.431 fetches/sec No Processes C 600.798 fetches/sec, No Processes Ruby 335.214 fetches/sec, 20 Processes Ruby 431.198 fetches/sec, I hope this helps. Best, Zev ___________________________________ fastcgi-developers mailing list http://fastcgi.com/fastcgi-developers/