WEBrick and mod_ruby performance

J

Jeff Mitchell

I've been scoping out ruby for an upcoming server project.

For my purpose, performance will be a factor because the server will
be slending data in real-time much like a multipayer game server such
as Quake (as opposed to waiting for user input). Quake is an extreme
example, though -- it wouldn't be nearly that demanding.

I am very impressed with WEBrick, and this would be my primary choice
were it not for performance concerns.

How does WEBrick scale? Looking through the code, it appears that new
requests are handled by a ruby Thread -- as opposed to a native thread
or a fork. What happens with 40 threads, all transferring data and
doing stuff, all being handled by a single ruby process setjmp-ing and
longjmp-ing around? I'm guessing performance would be poor.

Next option is mod_ruby. Now I don't even understand how mod_ruby
works with Apache 2.0 since the ruby interpreter isn't thread-safe.
So that's all a mystery to me. Apache 1.3 + mod_perl is probably
well-tested and perhaps the most appropriate choice.

Are the above assumptions correct, and are there other options? One
more option which comes to mind is to simply write a forking ruby
server from scratch. This would mean more development time, but how
much more I'm not sure.
 
A

ahoward

I've been scoping out ruby for an upcoming server project.

For my purpose, performance will be a factor because the server will
be slending data in real-time much like a multipayer game server such
as Quake (as opposed to waiting for user input). Quake is an extreme
example, though -- it wouldn't be nearly that demanding.

I am very impressed with WEBrick, and this would be my primary choice
were it not for performance concerns.

How does WEBrick scale? Looking through the code, it appears that new
requests are handled by a ruby Thread -- as opposed to a native thread
or a fork. What happens with 40 threads, all transferring data and
doing stuff, all being handled by a single ruby process setjmp-ing and
longjmp-ing around? I'm guessing performance would be poor.

Next option is mod_ruby. Now I don't even understand how mod_ruby
works with Apache 2.0 since the ruby interpreter isn't thread-safe.
So that's all a mystery to me. Apache 1.3 + mod_perl is probably
well-tested and perhaps the most appropriate choice.

Are the above assumptions correct, and are there other options? One
more option which comes to mind is to simply write a forking ruby
server from scratch. This would mean more development time, but how
much more I'm not sure.

you should definitely check out fastcgi and the ruby fastcgi binding. it's
AWESOMELY fast:

~ > ab http://eli/env.cgi | grep 'per second'
Requests per second: 4.04 [#/sec] (mean)

~ > ab http://eli/env.fcgi | grep 'per second'
Requests per second: 557.10 [#/sec] (mean)

(that's two orders of MAGNITUDE!)

~ > cat env.fcgi
#!/usr/local/bin/ruby
require 'cgi'
require 'fcgi'

FCGI.each_cgi do |cgi|
content = ''
env = []
cgi.env_table.each do |k,v|
env << [k,v]
end
env.sort!
env.each do |k,v|
content << %Q(#{k} => #{v}<br>\n)
end
cgi.out{content}
end


env.cgi is the exact same program - it runs either way: as a cgi or fcgi based
on extension. it's a terrible cgi i realize - but it demonstrates the speed
difference which can only get better, not worse:


here is a slightly more realistic benchmark and examples:

NORMAL CGI PROGRAM:

/usr/local/httpd/htdocs > ab http://127.0.0.1/a.cgi | grep 'Requests'
Requests per second: 10.83 [#/sec] (mean)

/usr/local/httpd/htdocs > cat a.cgi
#!/usr/bin/env ruby
require 'cgi'
require 'postgres'
require 'amrita/template'

# our template
html = <<-html
<html>
<body>
<ul><li id="tuples"></ul>
</body>
</html>
html
template = Amrita::TemplateText.new html

# this connection is made EVERY time!
pgconn = PGconn.new
tuples = pgconn.query "select * from foo"

# generate content from database
template.expand((content = ''), :tuples => tuples)

# blast out
cgi = CGI.new
cgi.out{ content }


FAST CGI PROGRAM (SAME PROGRAM PORTED TO FCGI):

/usr/local/httpd/htdocs > ab http://127.0.0.1/a.fcgi | grep 'Requests'
Requests per second: 245.58 [#/sec] (mean)

/usr/local/httpd/htdocs > cat a.fcgi
#!/usr/bin/env ruby
require 'cgi'
require 'fcgi'
require 'postgres'
require 'amrita/template'

# our template
html = <<-html
<html>
<body>
<ul><li id="tuples"></ul>
</body>
</html>
html
template = Amrita::TemplateText.new html

# this connection is made ONE time!
pgconn = PGconn.new

FCGI.each_cgi do |cgi|
tuples = pgconn.query "select * from foo"

# generate content from database
template.expand((content = ''), :tuples => tuples)

# blast out
cgi.out{ content }
end


still MUCH faster. some of the other advantages include being able to monitor
your web processes in top and NOT being able to affect the apache process.

as to your webrick questions i cannot say - but it does look _very_ cool.

-a
====================================
| Ara Howard
| NOAA Forecast Systems Laboratory
| Information and Technology Services
| Data Systems Group
| R/FST 325 Broadway
| Boulder, CO 80305-3328
| Email: (e-mail address removed)
| Phone: 303-497-7238
| Fax: 303-497-7259
| ~ > ruby -e 'p(%.\x2d\x29..intern)'
====================================
 
J

Jeff Mitchell

Dmitry Borodaenko said:
you should definitely check out fastcgi and the ruby fastcgi binding. it's
AWESOMELY fast:

~ > ab http://eli/env.cgi | grep 'per second'
Requests per second: 4.04 [#/sec] (mean)

What are you comparing it against: plain cgi, mod_ruby, or webrick?
~ > ab http://eli/env.fcgi | grep 'per second'
Requests per second: 557.10 [#/sec] (mean)

ahoward's post was unclear to me as well.

The performance of fastcgi would be essentially the same as
for mod_ruby, would it not?
 
A

ahoward

you should definitely check out fastcgi and the ruby fastcgi binding. it's
AWESOMELY fast:

~ > ab http://eli/env.cgi | grep 'per second'
Requests per second: 4.04 [#/sec] (mean)

What are you comparing it against: plain cgi, mod_ruby, or webrick?

plain cgi.

Linux 2.4.18-27.8.0 i686
httpd-2.0.47
ruby-1.6.8

-a
~ > ab http://eli/env.fcgi | grep 'per second'
Requests per second: 557.10 [#/sec] (mean)

====================================
| Ara Howard
| NOAA Forecast Systems Laboratory
| Information and Technology Services
| Data Systems Group
| R/FST 325 Broadway
| Boulder, CO 80305-3328
| Email: (e-mail address removed)
| Phone: 303-497-7238
| Fax: 303-497-7259
| ~ > ruby -e 'p(%.\x2d\x29..intern)'
====================================
 
A

ahoward

Why am I just now hearing about this?! Ugh. $40 on an apache book, oh
well, now I can put apache on my resume and forget about it. ;) Thanks
for the link.

this looks o.k. - but the ENTIRE webserver is blocked when running ONE cgi
program. eg. it's not a forking server. if you want speed, ease of
development, safety, and _scalability_ i'd check out using apache/fastcgi/ruby
- might want to hang on to that apache book. ;-)

-a

====================================
| Ara Howard
| NOAA Forecast Systems Laboratory
| Information and Technology Services
| Data Systems Group
| R/FST 325 Broadway
| Boulder, CO 80305-3328
| Email: (e-mail address removed)
| Phone: 303-497-7238
| Fax: 303-497-7259
| ~ > ruby -e 'p(%.\x2d\x29..intern)'
====================================
 
M

Michael Garriss

ahoward said:
this looks o.k. - but the ENTIRE webserver is blocked when running ONE cgi
program. eg. it's not a forking server. if you want speed, ease of
development, safety, and _scalability_ i'd check out using apache/fastcgi/ruby
- might want to hang on to that apache book. ;-)

Ah, ugh, dang, and that graph on the esehttpd site was so cool. Well
that book is still right next to my monitor, close call. ;) I wonder
if I can abstract away the server somehow so I can port my app to any
server?

I'm curious about using fastcgi with apache. Right now I'm not using
cgi.rb at all and just using the Apache::Request class (using my own
cookie class, etc). Are there speed benefits of using fastcgi over this
approach? If so can you give me a push in the fastcgi direction (a link
or whatever)?

TIA
Michael
 
A

Aredridel

--=-sM1ieajSrwzGIykxr9LU
Content-Type: text/plain
Content-Transfer-Encoding: quoted-printable
Ah, ugh, dang, and that graph on the esehttpd site was so cool. Well=20
that book is still right next to my monitor, close call. ;) I wonder=20
if I can abstract away the server somehow so I can port my app to any=20
server?
=20
I'm curious about using fastcgi with apache. Right now I'm not using=20
cgi.rb at all and just using the Apache::Request class (using my own=20
cookie class, etc). Are there speed benefits of using fastcgi over this=20
approach? If so can you give me a push in the fastcgi direction (a link=20
or whatever)?

cgi.rb is that abstraction. It handles apache requests, cgi and
fast_cgi all in the same code. An app written with fast_cgi in mind
using the CGI module will work in all three environs.

Ari

--=-sM1ieajSrwzGIykxr9LU
Content-Type: application/pgp-signature; name=signature.asc
Content-Description: This is a digitally signed message part

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.3 (GNU/Linux)

iD8DBQA/X2catP09exA3hooRAn5rAKDnPX+A7Yt1twlhmhChUBQeC65T2QCgrUwM
9D0l64qYmLYPuwMZ6zcSZqU=
=hnpK
-----END PGP SIGNATURE-----
0
--=-sM1ieajSrwzGIykxr9LU--
 
M

Michael Garriss

Aredridel said:
cgi.rb is that abstraction. It handles apache requests, cgi and
fast_cgi all in the same code. An app written with fast_cgi in mind
using the CGI module will work in all three environs.

Excuse my noobness on this. So when I do a look on RAA I find
FastCGI-0.5 by Eli Green and also I find that there is a mod_fastcgi
for apache. Which are we talking about? Or do I have to have
FastCGI-0.5 sit on top of mod_fastcgi?

Michael
 
I

Idan Sofer

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Excuse my noobness on this. So when I do a look on RAA I find
FastCGI-0.5 by Eli Green and also I find that there is a mod_fastcgi
for apache. Which are we talking about? Or do I have to have
FastCGI-0.5 sit on top of mod_fastcgi?
FastCGI is a communication protocol, so it requires support from both ends,
the web server and the "service".

The communication occurs either using stdin/stdout, UNIX socket domains or
TCP.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.2 (GNU/Linux)

iD8DBQE/X3MzHT1NNTuNW1YRAuWOAJwLTpriOYE7McXVsSJB27CiTWGbHQCgihce
TVOiZsshXeEXh1NFr3Qe2bc=
=vHCG
-----END PGP SIGNATURE-----
 
I

Idan Sofer

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

cgi.rb is that abstraction. It handles apache requests, cgi and
fast_cgi all in the same code. An app written with fast_cgi in mind
using the CGI module will work in all three environs.

Not entirely correct, fcgi can create cgi.rb enviroment, but that's not it's
native interface, same goes for mod_ruby.

Also, their are certain assumptions about the persistence of the application,
plain old cgi will never persist, while fastcgi is persistent by it's very
nature.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.2 (GNU/Linux)

iD8DBQE/X3UNHT1NNTuNW1YRAgbeAJsESmBbeFg46W1G/quFmlc5JWtNJACeKat9
gLr5ebSP9VGcn03gKEpuRek=
=j9Uf
-----END PGP SIGNATURE-----
 
M

Michael Garriss

Idan said:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1


FastCGI is a communication protocol, so it requires support from both ends,
the web server and the "service".

The communication occurs either using stdin/stdout, UNIX socket domains or
TCP.

Thanks for the info. I will look into fastcgi more carefully now.

Regards,
Michael
 
D

David Corbin

cgi.rb is that abstraction. It handles apache requests, cgi and
fast_cgi all in the same code. An app written with fast_cgi in mind
using the CGI module will work in all three environs.

Ari

But it doesn't abstract the response control for the three different environs.
Support fot thatis needed too.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,900
Latest member
Nell636132

Latest Threads

Top