rubys web performance

F

Florian Weber

hi!

i have to admit that im kinda disappointed by ruby because of its
poor web performance i've experienced so far.

i have a fairly complex application written in php. it does all kinds
of complex stuff, front controller, complex template system,
interceptors,
etc. even without any kind of acceleration which does any kind of
caching
for files, classes, etc, the app takes never longer than 0.2 seconds per
request.

when i have a simple app in rails now, which basically only takes about
100 rows
from one tables, puts it in objects and displays those in the view, the
request
takes 0.2 seconds with mod_ruby (all classes cached!) and with cgi
0.7 seconds.

on both systems (php and ruby) i measured without the invocation
overhead.
on the start of the script i set a variable to the current time and and
the end
i displayed the difference of the current time to the variable.

so basically the overhead created by cgi having to start a new ruby
interpreter
each time is ignored.

i know that rails is not really optimized for performance yet,
especially since
its not even released. however it feels like 0.55 seconds out of the
0.7 are
spend with the compilation of the ruby classes, before i even execute
any..


any ideas why? thanks a lot for feedback!

ciao!
florian
 
L

Lothar Scholz

Hello Florian,

FW> hi!

FW> i have to admit that im kinda disappointed by ruby because of its
FW> poor web performance i've experienced so far.

FW> i have a fairly complex application written in php. it does all kinds
FW> of complex stuff, front controller, complex template system,
FW> interceptors,
FW> etc. even without any kind of acceleration which does any kind of
FW> caching
FW> for files, classes, etc, the app takes never longer than 0.2 seconds per
FW> request.

FW> when i have a simple app in rails now, which basically only takes about
FW> 100 rows
FW> from one tables, puts it in objects and displays those in the view, the
FW> request
FW> takes 0.2 seconds with mod_ruby (all classes cached!) and with cgi
FW> 0.7 seconds.

FW> on both systems (php and ruby) i measured without the invocation
FW> overhead.
FW> on the start of the script i set a variable to the current time and and
FW> the end
FW> i displayed the difference of the current time to the variable.

FW> so basically the overhead created by cgi having to start a new ruby
FW> interpreter
FW> each time is ignored.

FW> i know that rails is not really optimized for performance yet,
FW> especially since
FW> its not even released. however it feels like 0.55 seconds out of the
FW> 0.7 are
FW> spend with the compilation of the ruby classes, before i even execute
FW> any..

I don't know rails but if you work with a non cgi architecture, like
FCGI, webrick, mod_ruby. Write an init page that requires all files
(not just the toplevel ones) that will be loaded.

I don't know if it is possible to change the GC behaviour because GC's
are done much to often in a normal environment, so if this has an
significant percentage, change the settings in "gc.c" and recompile
ruby.
 
F

Florian Weber

I don't know rails but if you work with a non cgi architecture, like
FCGI, webrick, mod_ruby. Write an init page that requires all files
(not just the toplevel ones) that will be loaded.

that means that mod_ruby and fcgi actually dont cache all the
loaded classes? i thought exactly thats what it does. when i profile
my ruby test, the execution via mod_ruby takes just about as
long as the execution under cgi minus the time it takes to load
the classes.

so here it seems like really all the classes are cached..

however im still wondering why my heavy php app, where
classes are not cached, no accelerator is used, etc is even a bit
faster than a super simple ruby example where classes are cached..
 
A

Andreas Schwarz

Florian said:
that means that mod_ruby and fcgi actually dont cache all the
loaded classes? i thought exactly thats what it does.

You are right.
however im still wondering why my heavy php app, where
classes are not cached, no accelerator is used, etc is even a bit
faster than a super simple ruby example where classes are cached..

I don't know rails, but all the ruby web frameworks I looked at were
extremely memory and CPU intensive. If you use the relational DB like it
is supposed to, without a generic OO mapping layer, and a simple
templating system like Kwartz, you will see that performance is similar
to PHP.
 
F

Florian Weber

I don't know rails, but all the ruby web frameworks I looked at were
extremely memory and CPU intensive. If you use the relational DB like
it
is supposed to, without a generic OO mapping layer, and a simple
templating system like Kwartz, you will see that performance is similar
to PHP.

well, even when i dont do any orm or database stuff at all its fairly
slow. in general it feels like the compilation of the classes and
modules
is the bottleneck..
 
A

Andreas Schwarz

Florian said:
in general it feels like the compilation of the classes and modules
is the bottleneck..

Of course, but there is a solution: use fastcgi. Try PHP as CGI, it will
be as slow as a ruby CGI.
 
F

Florian Weber

Of course, but there is a solution: use fastcgi. Try PHP as CGI, it
will
be as slow as a ruby CGI.

not really. like i said, i didnt measure the overhead created by the
fact
that cgi has to start up a interpreter each time. i just stop from the
start
of the script to the end. directly within the script..

i just tried something:

#!/usr/local/bin/ruby

start = Time.now
require 'yaml'
require 'logger'
t = Time.now - start

print "Content-type: text/html\r\n\r\n"
print "%.3f sec.\n" % t.to_f


this alone takes already at least 0.13 seconds (via cgi)

when i run it just via the shell it takes 0.09 seconds, which i think
is already quite a lot... no?


ciao!
florian
 
A

Andreas Schwarz

Florian said:
not really. like i said, i didnt measure the overhead created by the
fact
that cgi has to start up a interpreter each time. i just stop from the
start
of the script to the end. directly within the script..

i just tried something:

#!/usr/local/bin/ruby

start = Time.now
require 'yaml'
require 'logger'
t = Time.now - start

print "Content-type: text/html\r\n\r\n"
print "%.3f sec.\n" % t.to_f


this alone takes already at least 0.13 seconds (via cgi)

Where's the problem? You have to load the files only once, so it doesn't
matter how long it takes to parse them. CGI is no use for "real"
applications, use fastcgi, webrick or mod_ruby.
 
F

Florian Weber

Where's the problem? You have to load the files only once, so it
doesn't
matter how long it takes to parse them. CGI is no use for "real"
applications, use fastcgi, webrick or mod_ruby.

well, but i think thats exactly the point why ruby is really hard to use
for general web stuff..

there are barely any hosters who support fastcgi, webrick or mod_ruby.
especially since the last one is not usable for shared hosting. so you
have to rely on cgi..

and anyways, why does it take ruby so long to load the files and compile
it when the same would only take a fragment of it with php?
 
A

Aredridel

and anyways, why does it take ruby so long to load the files and compile
it when the same would only take a fragment of it with php?

In short, PHP is optimized for ease of computer parsing.

Ruby is optimized for human parsing.
 
F

Florian Weber

In short, PHP is optimized for ease of computer parsing.

Ruby is optimized for human parsing.

hehe.. 'my application is really slow, but thats because the application
is optimized towards high usability' ; )
 
A

Andreas Schwarz

Florian said:
well, but i think thats exactly the point why ruby is really hard to use
for general web stuff..

there are barely any hosters who support fastcgi, webrick or mod_ruby.
especially since the last one is not usable for shared hosting. so you
have to rely on cgi..

I agree, ruby support on shared servers is poor. This is one of the
reasons why I'm using a virtual server from www.vdserver.de.
and anyways, why does it take ruby so long to load the files and compile
it when the same would only take a fragment of it with php?

Did you really try PHP CGI with source files of comparable size (don't
forget that every file you require could itself require other files)?

I don't know exactly how the parsing mechanism in PHP and Ruby differs,
and I don't know if there is actually a difference in performance; but
I wouldn't be surprised if PHP was faster, because the language is
*much* simpler to parse than Ruby. However, I don't think it's really a
problem.
 
G

gabriele renzi

il Mon, 21 Jun 2004 01:50:01 +0900, Florian Weber
<[email protected]> ha scritto::

just one thing: How did youm measured time?
IIRC you should be using Process.times.utime but actually don't
remember why :/
 
G

gabriele renzi

il Mon, 21 Jun 2004 07:55:25 +0900, Florian Weber
and anyways, why does it take ruby so long to load the files and compile
it when the same would only take a fragment of it with php?

I just thought of this: does rails uses ERB or ERuby ?
The first one is basically a pure ruby version of the latter, maybe if
that is the one used you may seicth to the C one and get some better
performance..
 
F

Florian Weber

il Mon, 21 Jun 2004 07:55:25 +0900, Florian Weber


I just thought of this: does rails uses ERB or ERuby ?
The first one is basically a pure ruby version of the latter, maybe if
that is the one used you may seicth to the C one and get some better
performance..

its not really a issue with rails..

its a issue with the performance ruby reads and compiles files..

see my email before about how i tested it. there i only required to
files. no rails stuff going on..
 
D

David Garamond

Florian said:
i just tried something:

#!/usr/local/bin/ruby

start = Time.now
require 'yaml'
require 'logger'
t = Time.now - start

print "Content-type: text/html\r\n\r\n"
print "%.3f sec.\n" % t.to_f


this alone takes already at least 0.13 seconds (via cgi)

when i run it just via the shell it takes 0.09 seconds, which i think
is already quite a lot... no?

try php cgi with several php extensions pre-loaded in php.ini, it can
take up to 0.30-0.40 second on my machine (the overhead is mainly in
opening *.so files).
 
D

David Garamond

Andreas said:
Did you really try PHP CGI with source files of comparable size (don't
forget that every file you require could itself require other files)?

I don't know exactly how the parsing mechanism in PHP and Ruby differs,
and I don't know if there is actually a difference in performance; but
I wouldn't be surprised if PHP was faster, because the language is
*much* simpler to parse than Ruby. However, I don't think it's really a
problem.

my experience with php seems to confirm this. php compilation is so fast
that it's okay to use PHP CGI for medium traffic and simple to medium
application complexity.

*but*, if your application needs to compile 1000+ lines of php code on
every request (e.g. you include/require several libraries, like PEAR
modules), the overhead does start to show itself (0.5-1 seconds or more
of delay).

php cgi apps seems faster since most libraries are written in C, while
Perl's (and Ruby's) are written in pure Perl/Ruby code so they need to
compile many lines of code per request. but this situation is changing
everyday that PEAR is more and more used everyday...
 
D

David Garamond

Florian said:
its not really a issue with rails..

its a issue with the performance ruby reads and compiles files..

see my email before about how i tested it. there i only required to
files. no rails stuff going on..

note: php 4.3.6, ruby 1.8.1, both on Linux

<<<
* 0 line of code:

$ time ruby -v; # 0.023s
$ time php -v; # 0.037s (note: only mysql.so dynamic PHP extension is
loaded; but several exts are builtin)

* 1 line of code:

$ echo '<? echo "Hello, world!\n" ?>' | time php -q; # 0.037s
$ time ruby -e'puts "Hello, world!"'; # 0.023s

* +- 1750 lines of PHP code:

$ time php /usr/share/pear/System.php; # 0.058s
$ wc System.php PEAR.php Console/Getopt.php
540 2002 17972 System.php
975 3290 30154 PEAR.php
251 1084 9536 Console/Getopt.php
1766 6376 57662 total

* +- 2600 lines of Ruby code:

$ time ruby cgi.rb; # 0.065s
$ wc cgi.rb English.rb delegate.rb
2318 9250 75713 cgi.rb
155 855 5732 English.rb
139 322 2942 delegate.rb
2612 10427 84387 total

Conclusion: Not disappointing for Ruby...

The problem is, for simple CGI web app, thousands of Ruby lines
typically need to be parsed & compiled, while only several lines are
needed for PHP (due to PHP extensions are in the form of compiled
machine code).

Hope things will get better with Cardinal or Ruby2... Overhead of
scripting languages compilation (esp. Perl & Ruby, since those doesn't
fully support precompiled code) almost always force me to make
persistent/long-running processes/daemons (which have problems of their
own), or go to C (which I can't stand :).

For example, for an SMTPD I have to ditch qpsmtpd (since the script runs
via tcpserver, i.e. needs to be forked on every request) and make my own
Perl daemon. The overhead would just really burden my machine.
 
M

Michael Neumann

its not really a issue with rails..

its a issue with the performance ruby reads and compiles files..

see my email before about how i tested it. there i only required to
files. no rails stuff going on..

Can you show us your PHP file which you used for measuring?

The libraries you loaded are not pure C extensions! Have a look at the
number of lines:

library | source lines
--------|-------------
yaml | 4158
logger | 728
cgi | 2909

So I guess, compiling ~5000 lines in 0.09 seconds, is not that bad at
all. This gives a rate of 50.000 lines per second.

Now try the same in PHP, and measure again.

Regards,

Michael
 
T

Thomas Fini Hansen

my experience with php seems to confirm this. php compilation is so fast
that it's okay to use PHP CGI for medium traffic and simple to medium
application complexity.

I'd go with this, and the statement that PHPs syntax is 'optimized'
for parsing. Actually it chokes on stuff like $obj->ary[$i]->value;
(alledgedly it's improving in PHP5, like many other things).
*but*, if your application needs to compile 1000+ lines of php code on
every request (e.g. you include/require several libraries, like PEAR
modules), the overhead does start to show itself (0.5-1 seconds or more
of delay).

True again. I often test things on an old 300Mhz box, to slow things
down to a speed where I can actaully gauge the speeds. Larger projects
like phpgroupware get extremely slow, which make you think twice
before throwing them on the big iron.

And don't forget that Ruby can be doing catchup when actually running
the code. I've seen Ruby code that was several factors faster than the
equvalent PHP code, doing a lot of throwing data around.
php cgi apps seems faster since most libraries are written in C, while
Perl's (and Ruby's) are written in pure Perl/Ruby code so they need to
compile many lines of code per request. but this situation is changing
everyday that PEAR is more and more used everyday...

And while we're talking about lines.. I had to fix the code in
SquirrelMail that encodes the headers when there's non-ASCII
characters in it. Thought that it would be easy as I'd done my own in
Ruby for another project and it was just 7 lines of code. Imagine my
surprise when I found out that it was 118 lines of PHP code. About 10
was 'extra' code for stuff related to SquirrelMail.

I couldn't resist, first I tried rewriting the function to exec
Ruby. Slow as hell, but only 19 lines. Then I ported my Ruby function
as well as I could and it ended up at 32 lines. So even if we subtract
the 10 lines, it's still the difference between 7 and 22 lines.

My own conclusion is that, while Ruby might be slow on the uptake
sometimes, it's not because it's inheriently slower.
 

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,774
Messages
2,569,599
Members
45,165
Latest member
JavierBrak
Top