Zed and Luis drop the bomb on Ruby's poor performance

[email protected] wrote:


you make good points - but let me just throw in my 2 cts:

virtual machines are stupid. java is slow. c++ is slow. python is slow.
ruby is slow. so what. if you want fast you need c or fortan or
assembler.

Ara, do you not see value in a Ruby VM, or is just that speed is not, in
itself, a justification for a VM?

(The speed-related advantage to a VM is that it does not require one to
know C, etc., or have a compiler for all target platforms. Maybe not
as fast as tight compiled C, but also not as much trouble. It’s a
trade.)


James B.

“You harmonize; then you customize.”

  • Wilson Pickett

On 5/22/06, Kirk H. [email protected] wrote:

The thing that always stands out to me in these performance discussions is
that people argue that Ruby needs a performance improvement, but there are
rarely any specifics attached to that analysis.

How much of speed improvement? How fast should Ruby be? For what?

Please don’t get me wrong, I really like Ruby. However, just because
I like Ruby doesn’t mean that I can start using it to develop
applications within our corporation (I work for a large corporation).
When I brought up using Ruby for application development with my
senior IT manager, he was concerned about:

(1) Performance: Here, the question is NOT about ‘how fast should Ruby
be’, but is about what people who have the capacity to make
‘significant’ corporate decisions are ‘being told’ about Ruby’s
performance by consultants. I have seen presentations by
‘well-established’ consulting companies that show Ruby’s performance
to be an order of magnitude slower than Java for web apps. I don’t
have time to develop benchmark tests comparing the two languages, but
have to depend on Ruby app. developers to produce those benchmarks;
unfortunately I cannot find them easily. Now, Zed (I would consider
him an authority on Ruby) comes out and talks about performance issues
with Ruby (and YARV will solve it in the future). How am I now to
convince my manager that Ruby is ‘better’ (within the context of
performance)?

The reason why IT managers want ‘performance’ even if the application
really doesn’t require it, is to cover their behinds, among other
thing. For example, if the website is slow, they don’t want it to be
attributed to the language, even if that is not the case (could be a
network problem, but the network group would more willingly point
their fingers at the app. development group for their choice of
language than to accept their problem); has happened before and will
happen again.

So, here ‘performance’ is not for the sake of performance demanded by
the application, but for the sake of ‘not wanting to be talked to by
the boss’. That is the reason I said that many IT managers make
‘performance’ decisions based on ‘feelings’, not necessarily had data.

(2) Using two different languages for different performance needs:
Some fellow Rubyists have said that they would switch to C if their
app. needed performance boosts. This will work if it is a personal or
small project. But when in an large corporation, switching between
languages to get performance gains will result in maintenance
nightmares. Many IT managers understand this and have experienced
this. Combined that with the mantra ‘Java is fast’ preached by many
consultants, and the decision for the senior IT manager becomes easy:
one language that can be used for apps that require real performance
and for ones that don’t: Java.

(3) Survival of Language: This is another bigee. If the IT manager OKs
a language that happens to be a fad, then he might as well bid goodbye
to his job (lost productivity, cost, etc). So, they want to be sure
that the language is going to be in the ‘main stream’ for a long time.
In their mind, the only way they can be assured of that is:
(a) if a large corporation is going to support it – not
necessarily the language, but any application build using the
language. The thinking goes that if a large corporation is going to
put its weight behind the language, then that corporation will not let
the language die. This is what I meant when I said ‘lack of corporate
support for Ruby on Rails’; I don’t mean to belittle the corporations
that are offering support for Ruby on Rails, but I am talking from a
large corporation’s point of view. A good case study would be on how
Linux got its foot hold into the corporate world.

Once again, if Ruby’s vision is not to penetrate the corporate
environment as Ryan pointed out (but would be a nice validation if it
indeed penetrate the corporate world by some means), then this
discussion is moot. Knowing that, I wouldn’t try to push Ruby to my
managers; I will use it for personal projects.

On the other hand, if Ruby has a dream of penetrating the corporate
world, then it needs a marketing machine that would deal with the real
and, more importantly, the ‘illusionary’ problems created in the
corporate world – just like Firefox’s or Linux’s marketing machine.
Unfortunately, penetrating the corporate world by some means is
never going to happen, unless an concerted effort is made.

Just some thoughts from a guy who has been in the IT hot seat before,
and is glad he is no longer there!

Sorry for this long post.

-Madan.

On Tue, 23 May 2006, Victor S. wrote:

Makes sense. But.
I’d like to think about things like “reasonable slow” and “unreasonable
slow”; and Ruby sometimes is just unreasonable slow. Here are some
examples:

  • I’m working with custom UI library, which is based on HTML (namely, on
    HTMLayout – Terra Informatica Software). There are a large amount of objects created
    corresponding to DOM tree nodes (“large” means thousands) and profiler says,
    that one of the slowest operation is Class#new - is it normal?

devil’s advocate: yes it makes sense that ‘new’ is slow. it’s generally
slow
in all langs, including c++ (where stl insertion causes 3 of ctors and
the
profiler will show this) and perl, which is claimed faster than ruby
but, when
objects are used, crawls compared to ruby because object creation is so
bad in
it. the fact that object creation is so slow is why people historically
don’t
represent chars as objects in text editors. that said, perhaps it can
be sped
up - at least this is a good, concrete example!

  • 5000 objects is loaded from database (by SELECT’ing and setting fields).
    The major slower is that each object has Date field (Integer#gcd is very
    slow). Or Kernel#send (I use it because of my DSL created) and so on.

probably this could be sped up too - but your point is taken.

Summarizing, after large profilings and optimizations, there are oftenly
some core methods (even Fixnum#+) show themselves as major speed problems.

This situation I call “unreasonable slow”.

i like where you are going with this - let’s see if a critical analysis
of
some ‘real’ issues sheds light on whether they point to the need for a
vm (my
feelings are that it will not, but i’d be happy to be proven wrong). i
can’t
think of a better way than to post some specific code and see what
people can
do with it. history has shown that posting such challenges to the list
yields
at least an order of magnitude speed-up, if it doesn’t i’d say you are
correct - anyone have an example less than 100 lines or so we can play
with?
without an example i’m afraid this discussion will be little more than
hot
air. let’s get something real to work with, prove that it is
‘unreasonably’
slow, and then discuss.

kind regards.

-a

From: [email protected] [mailto:[email protected]]

that one of the slowest operation is Class#new - is it normal?
represent chars as objects in text editors. that said, perhaps it can be
sped
up - at least this is a good, concrete example!

Caugh… I’ve thought, that the main reason not to have an object for
each
char is memory reason… But I can miss.
BTW, I was the C++ guy before Ruby, and I’ve never seen object creation
took
a noticeable amount of performance. As well as other “simple core”
operations, like working with numbers and the same stuff.
Hence my astonishement, when after optimizing, optimizing, optimizing my
program with large UI and DB operations I see the top time-eating
methods is
not UI, not DB, not sorting or filtering large arrays, but dumb stuff
like
Fixunum#+ or Class#new.

‘unreasonably’
slow, and then discuss.

OK, maybe later. Right now I haven’t any “small function which is too
slow”,
but entire program works with unacceptable speed.
On my old Celeron 900 I can hardly debug it (but even on more modern
1500+
and 2000+ machines, which are normal in Ukraine, it also works slow).

-a

Victor.

On Tue, 23 May 2006, James B. wrote:

itself, a justification for a VM?
i’m saying that gcc kills any vm both on speed and portability,
including
windows, and has decades of hard work put in.

(The speed-related advantage to a VM is that it does not require one to know
C, etc., or have a compiler for all target platforms. Maybe not as fast as
tight compiled C, but also not as much trouble. It’s a trade.)

hmmm. i think sun’s experience with the java vm shows otherwise -
remember
when you couldn’t even ‘stop’ threads! i think making a fast, protable,
vm is
a lions job. however, i’d be quite happy to be wrong, it just seems
un-likely. consider how long has parrot been ‘almost’, for example…

-a

On 5/22/06, Madan M. [email protected] wrote:

I like Ruby doesn’t mean that I can start using it to develop
have time to develop benchmark tests comparing the two languages, but
have to depend on Ruby app. developers to produce those benchmarks;
unfortunately I cannot find them easily. Now, Zed (I would consider
him an authority on Ruby) comes out and talks about performance issues
with Ruby (and YARV will solve it in the future). How am I now to
convince my manager that Ruby is ‘better’ (within the context of
performance)?

Read what Zed said about Rails app performance though. Even though
Ruby can be slow, he said that with its built in caching, Rails apps are
often
faster than Java Web apps.

The reason why IT managers want ‘performance’ even if the application
really doesn’t require it, is to cover their behinds, among other
thing. For example, if the website is slow, they don’t want it to be
attributed to the language, even if that is not the case (could be a
network problem, but the network group would more willingly point
their fingers at the app. development group for their choice of
language than to accept their problem); has happened before and will
happen again.

sorry, but if you don’t have the logging/instrumentation to show where
the
slowdown is, it doesn’t matter what language you’ve written in. Using
a languages because its marketing is better in order to “protect”
yourself
is a good way to end up in bigger trouble down the line. Profile,
Optimize,
Log. Hard, verifiable numbers will win everytime – if they don’t
you’ve got
another problem.

So, here ‘performance’ is not for the sake of performance demanded by
the application, but for the sake of ‘not wanting to be talked to by
the boss’. That is the reason I said that many IT managers make
‘performance’ decisions based on ‘feelings’, not necessarily had data.

see above.

you don’t need to switch out the whole language. Ruby uses C extensions
quite readily and they’re not too hard to write (RubyInline makes it
even
easier.) You still get something that looks and feels like Ruby from
the
high level view, only the bottleneck(s) have been replaced.

The remainder of this email is off topic to the general performance
thread,
but I find it to be wrong-headed as well. If need be, maybe we should
start
another email thread to discuss Ruby and it’s commercial support or lack
thereof.

Madan M. wrote:

corporate world – just like Firefox’s or Linux’s marketing machine.
Unfortunately, penetrating the corporate world by some means is
never going to happen, unless an concerted effort is made.

Ruby doesn’t have a vision or a dream; Rubyists have dreams and visions.

Ruby is what you make it.


James B.

“You harmonize; then you customize.”

  • Wilson Pickett

On May 22, 2006, at 11:59 AM, pat eyler wrote:

needed to solve the problem. One solution in the works is a real
virtual machine called Rite (or YARV depending on who you talk to)
which is showing some real promise and seems to be speed
competitive with the fastest Java implementations.

I think you’re quoting selectively here. There are some counter
points in
both interviews.

Of course I engaged in selective quoting. That’s 90% of the fun! :slight_smile:

So what is being done to get YARV the attention it deserves? Why
aren’t we talking about it all the time? What can I personally do to
help? Are there valid excuses for not focusing on improving Ruby’s
poor computational performance?

Are you on the Ruby Core mailing list? Are you posting bugs and
feature requests to the trackers? Have you downloaded and built
YARV so that you can test it on your system? All of these are ways
you can get involved and help out.

I am on ruby-core but mostly just so I can bask in the glow of the
smart people on that list. Plus, I have submitted at least one bug
report to that least (only to have it turn out to be clumsy handling
if IPv4 and IPv6 on OSX).

I have not yet downloaded and built YARV, but I will in the very near
future. I am not a great programmer, but as a result I do find neat
little test cases that can try the patience of even the most liberal
parser & compiler!

cr

On 5/22/06, James B. [email protected] wrote:

Ruby doesn’t have a vision or a dream; Rubyists have dreams and visions.

Ruby is what you make it.

Thanks for catching my faux pas! I should have written: ‘If Rubyists
have a vision to …’ instead of ‘If Ruby’s vision …’

-Madan.

On Tue, 2006-05-23 at 01:32 +0900, Peter H. wrote:

The problem is that Zed and Luis make out that performance is something
that the whole Ruby community is deliberately ignoring. This is not the
case, there are plenty of people who have no issue with the performance
of Ruby. The truth is the performance is an issue for Zed and Luis and
they are trying to make out that it is not their personal bugbear but
some sort of conspiracy so they don’t look like whiners. I have never
though “damn Ruby’s dismal performance, it should be able to do this
faster” and I probably never will.

Hey Peter, thanks for deliberately ignoring my whining. Now, if you’ll
excuse me I have to go and continue to security audit the C extensions
in Mongrel so that I can be sure there’s no buffer overflows.

Man, if only Ruby were faster. Then I wouldn’t have to write so much
stuff in C and could just worry about crafting beautiful code. Oh well,
back to work on my C … I mean Ruby … program.

On 5/22/06, pat eyler [email protected] wrote:

On 5/22/06, Madan M. [email protected] wrote:

On 5/22/06, Kirk H. [email protected] wrote:

Read what Zed said about Rails app performance though. Even though
Ruby can be slow, he said that with its built in caching, Rails apps are often
faster than Java Web apps.

Pat, that is exactly the point: Ruby is slow; so you have to create
work arounds! Not something I would like to hear, if I were evaluating
a language.

We need a version of Ruby that is comparable in execution speed to
Python or Java. If it is YARV, then let us roll it out fast (no pun
intended)

-Madan.

Re: Zed and Luis drop the bomb on Ruby’s poor performance

On Tue, 23 May 2006, Victor S. wrote:

Caugh… I’ve thought, that the main reason not to have an object for each
char is memory reason… But I can miss.

easy to avoid with flyweight pattern like fixnums in ruby. then one is
left
with performance of object lists vs. sequential memory strings.

BTW, I was the C++ guy before Ruby, and I’ve never seen object creation took
a noticeable amount of performance. As well as other “simple core”
operations, like working with numbers and the same stuff. Hence my
astonishement, when after optimizing, optimizing, optimizing my program with
large UI and DB operations I see the top time-eating methods is not UI, not
DB, not sorting or filtering large arrays, but dumb stuff like Fixunum#+ or
Class#new.

we are obiviously working in different programming domains - but it does
sound
like you have real issues, just ones i’ve never experienced…

OK, maybe later. Right now I haven’t any “small function which is too slow”,
but entire program works with unacceptable speed. On my old Celeron 900 I
can hardly debug it (but even on more modern 1500+ and 2000+ machines, which
are normal in Ukraine, it also works slow).

ok then - your contribution, whenever you have time, of code will
certainly
help the cause to speed-up ruby or, on the contrary, to decide there is
no
problem. we really need examples to spend our energy productively i
think.

cheers.

-a

I’ve always had a sense that some of what makes Ruby so beautiful is
precisely what makes it slow. Some of this is a matter of
implementation (if anyone remembers the early implementations of ML,
you know what good tail-recursion can do for you. Plus Ruby seems to
get super-linearly worse as its working set grows), but some of it is
fundamental. Metaprogramming is very hard to do without depending on a
lot of string comparing at runtime. I’ve got a language design
background (I made a lot of money writing compilers for scripting
languages), and I’ve had to deal with this problem in other languages.
YARV looks like beautiful work, but I have a gut-feeling that it won’t
solve the “speed” problem all by itself.

I won’t wade into the whole “is Ruby fast enough” question because
defining “enough” really deserves its own thread. It’s an important
question though, especially as regards Ruby in corporate IT.

Quoting [email protected], on Tue, May 23, 2006 at 01:50:34AM +0900:

Those people having speed issues: Is it not a reasonable option to
replace the bottleneck Ruby code with custom compiled C libraries?

Its not obvious that this can always help, though it might in some
cases.

I’ve been benchmarking vpim’s icalendar decoding, and haven’t found any
way to get it significantly faster yet.

Its a bit of an issue, a utility I use a lot to print out events and
todos for the next week usually takes 5-10 seconds to run. This is long
enough to notice!

When I tried running profile, and it told me 40% of the time was spent
in String case-insensitive comparisons, so I reworked the internals to
always uppercase strings so that wasn’t necessary. Got about 5%.

I even tried using symbols instead of strings, I expected from lisp
experience that symbol comparisons would be really fast, but they
are only slightly faster (for strings of the size I’m working with
anyway). **

I ran out of time at that point, but its not clear to me what kind
of algorithmic changes I can make to speed things up, and I’m not too
sure where the time is being spent, other than in string operations.

There definitely isn’t one part of the app I can point to and say
“recode that in C and my problems will go away”. Also, you might have
noticed but ruby libraries that require extensions to be compiled tend
to not get a lot of traction in the ruby community.

Anyhow, I just spent a weekend on performance tuning, I might still find
out some clever way to restructure my code so that it gets twice as
fast, but a 2-3 times speed improvement would make a big difference to
my library. The difference between 6 seconds and under 2 seconds is huge
in human interface terms.

Cheers,
Sam

**

                      user     system      total        real

noop 0.700000 0.000000 0.700000 ( 0.698633)
String#== 2.410000 0.010000 2.420000 ( 2.445288)
String#casecmp 2.650000 0.000000 2.650000 ( 2.652620)
Symbol#== 2.280000 0.000000 2.280000 ( 2.274505)
String#to_sym 2.460000 0.000000 2.460000 ( 2.449362)
String#up 4.730000 0.000000 4.730000 ( 4.721140)
String#up#to_sym 6.030000 0.000000 6.030000 ( 5.986897)

– bench.rb –
require ‘benchmark’
require ‘pp’

str0 = “a” * 20
str1 = str0.upcase
sym0 = str0.to_sym
sym1 = str1.to_sym

$N = 1000000

Benchmark.bm(20) do |x|

x.report("noop")  do
$N.times do
end

end

x.report("String#==")  do
$N.times do
  str0 == str1
end

end

x.report("String#casecmp")  do
$N.times do
  str0.casecmp(str1)
end

end

x.report("Symbol#==")  do
$N.times do
  sym0 == sym1
end

end

x.report("String#to_sym")  do
$N.times do
  str1.to_sym
end

end

x.report("String#up")  do
$N.times do
  str1.upcase
end

end

x.report("String#up#to_sym")  do
$N.times do
  str1.upcase.to_sym
end

end

end

On May 22, 2006, at 3:49 PM, Sam R. wrote:

I even tried using symbols instead of strings, I expected from lisp
experience that symbol comparisons would be really fast, but they
are only slightly faster (for strings of the size I’m working with
anyway). **

Don’t forget that string comparison is pretty quick if the strings
differ in the first character. If you try comparing to the same
string and make the string a lot longer (say 2000 characters) you’ll
get a situation where symbol comparisons are about three times faster
than string comparisons.

You also need a better noop. If you call a method in there that does
nothing then I’m getting:

                       user     system      total        real

noop 0.490000 0.000000 0.490000 ( 0.664154)
do nothing method 1.650000 0.030000 1.680000 ( 2.501031)
String#== 3.030000 0.040000 3.070000 ( 4.191784)
String#eql? 2.930000 0.030000 2.960000 ( 4.237489)
String#equal? 1.300000 0.010000 1.310000 ( 1.858182)
Symbol#== 1.310000 0.020000 1.330000 ( 1.979673)
Symbol#eql? 1.300000 0.010000 1.310000 ( 2.036749)
Symbol#equal? 1.310000 0.010000 1.320000 ( 1.727041)

(this is on OS X… ignore the real time since it is pretty much
random on OS X)

Have you tried profiling your code?


Bob H. – blogs at <http://www.recursive.ca/
hutch/>
Recursive Design Inc. – http://www.recursive.ca/
Raconteur – http://www.raconteur.info/
xampl for Ruby – http://rubyforge.org/projects/xampl/

Hi Sam!
user system total real

noop 0.700000 0.000000 0.700000 ( 0.698633)
String#== 2.410000 0.010000 2.420000 ( 2.445288)
String#casecmp 2.650000 0.000000 2.650000 ( 2.652620)
Symbol#== 2.280000 0.000000 2.280000 ( 2.274505)
String#to_sym 2.460000 0.000000 2.460000 ( 2.449362)
String#up 4.730000 0.000000 4.730000 ( 4.721140)
String#up#to_sym 6.030000 0.000000 6.030000 ( 5.986897)

[…]
x.report(“Fixnum#==”) do
$N.times do
0 == 1
end
end
[…]
x.report(“String#up!”) do
$N.times do
str1.upcase!
end
end
[…]

                      user     system      total        real

noop 0.157000 0.000000 0.157000 ( 0.156000)
Fixnum#== 0.390000 0.000000 0.390000 ( 0.391000)
String#== 0.438000 0.000000 0.438000 ( 0.437000)
String#casecmp 0.578000 0.000000 0.578000 ( 0.594000)
Symbol#== 0.390000 0.000000 0.390000 ( 0.390000)
String#to_sym 0.563000 0.015000 0.578000 ( 0.579000)
String#up 1.437000 0.016000 1.453000 ( 1.484000)
String#up! 0.532000 0.000000 0.532000 ( 0.531000)
String#up#to_sym 1.890000 0.000000 1.890000 ( 1.922000)

Well i think in this trivial cases the problem isn’t the string
compare or whatever C algorithm is called - the problem is the call
itself. (two trivial fixnum compares are already more expensive
than a single String compare)

String#upcase constructs a new object (using the bang method is
way faster)

Conclusion: method calls in general and object creation are the
bottlenecks in this (very, very) simple cases.

cheers

Simon

Quoting [email protected], on Tue, May 23, 2006 at 05:12:14AM +0900:

Hi Sam!

Hi Simon,

Conclusion: method calls in general and object creation are the
bottlenecks in this (very, very) simple cases.

My conclusion as well.

My real app basically runs over all the lines in a set of files using
IO#each, runs a regex, turns the matched strings into objects, so is
pretty much dominated by these simple cases (I think, and profile
suggests).

Your !-optimizations are interesting. I’ll look back at my low-level
code. Maybe by changing my “name = $2.upcase” statements to “name = $2;
name.upcase!” I can get some good speedups. Depends on whether I need to
keep both versions around, I’ll have to construct some test cases and
profile them.

Thanks,
Sam

Sam R. wrote:

My real app basically runs over all the lines in a set of files using
Thanks,
Sam

There were some performance tips posted here some time ago, keeping the
number of objects low is definitely a good start. I just don’t like the
bang methods because you can’t method-chain with them. (a lot of the
return nil if there is no change)

If the files aren’t that big try to read them in one big read - should
be way faster.

Another one of the tips posted before was: use sqlite - and i can
wholeheartedly support that. If you have the chance to change your data
format to a sqlite database you can run a select on thousands of
lines in virtually no time. (and it’s really, really painless to use)

cheers

Simon

The elephant in the room is that programmers can’t put the importance
of execution speed into perspective :slight_smile:

There isn’t a lot of discussion on the Ruby list because execution
speed isn’t the biggest issue for most people.

However, when execution speed is an issue it can be a bad bad thing.


Anyhow, here are a few random thoughts (with some real numbers)
around the issue.


First off. Premature optimisation. We’ve all heard of it, even heard
that’s it is bad. Okay. Quick quiz. Which loop is faster?

#1
for i in 1…(a.length - 1) do
… do something to a[i]
end

or

#2
a.each { | thing | … do something to thing }

or

#3
for thing in a do
… do something to thing
end

??

In Ruby 1.6.x #1 was a bit faster than #3 which was a lot faster than #2

(When I replaced the ‘each’ loop form in xampl-pp – an XML pull
parser that I wrote – with the ‘for … in’ loop form the throughput
of the parser was increased by 2-4 times).

In Ruby 1.8.4, #3 is about 15% faster than #2 which is quite a lot
faster than #1

(So, I know how to speed up my parser, but I have not done this
yet… it is working well enough and because the real speed up is to
go to libxml or something).

So. What happened? What we consider to be idiomatic Ruby is now only
a little slower than non-idiomatic Ruby. What would have happened if
the community had really regarded execution speed as a primary
criteria? We’d have a different idea of ‘idiomatic’ is what.

Ruby’s focus is on something other than performance.


So what happens when speed is important and you’ve already optimised
your algorithms? These days you move out of Ruby. That’s your only
option. I thank Zed for doing that with Mongrel – it makes a big
difference.

Would a VM have helped? Sure. Sufficiently? I doubt it. Java is what,
ten times faster than Ruby? Lets say. Is that sufficient to actually
solve the problem?

Not for a lot of the examples that come up.

Definitely not for me.


Here’s an example. I’ve got a system written in Rails that is a kind
of multi-user authoring tool that runs as a webapp. My customers
build multiple inter-dependent websites using it. Publishing takes
anywhere from 7 to 45 seconds. This is Rails we are talking about
here… nobody gets to do anything while that publishing is going on.
There are a number of ways to alleviate the problem (in particular
async publishing using DRb or something like that).

Thing is, I got bored last weekend and decided to re-write the main
culprit in Common Lisp. I’m using the liquid templating system
because it is simple, my customers like it, and you can’t change any
data when using it. But it is slow (with respect to my applications
requirements) – I still recommend it. Common Lisp is roughly the
speed of C++, maybe a tad faster these days (actually, on OS X with
that obnoxious gcc 4.x error that prevents compiling at higher
optimisation levels than O1, CL is quite a bit faster than C even –
but lets not go there). The CL version of liquid was more than 120
times faster than Ruby – and I did nothing to optimise the code.
That’s publishing in less than 0.4 seconds in CL, 45 seconds in Ruby,
and lets be generous, 4.5 seconds in Java. Java doesn’t solve my
problem. I doubt a VM for Ruby would either.

What am I going to do? Well, first off, async publishing using DRb.
If I still have a problem I’ll rig up something with CL. No, I’m not
going to jump straight to CL (and just to be crystal clear here, I
like CL just fine, and I like Ruby just fine – I’ve just got other
higher priority things than raw execution speed to consider).


Lets talk a little more about webservers. I’ve written a lot of Java
based web applications over the years. I had a new webapp I had to
write and I was more than a little concerned with performance in
Java. I had prototyped something but it was horribly complex trying
to minimise page generation (it was a completely dynamic site, also
involving the construction of multi-page websites). So I wrote the
thing in Common Lisp in the end. Two things: first, it generated the
pages so quickly I didn’t have to optimise anything, it was quicker
to just re-generate; second, I used TBNL (slightly modified lisp
framework) to serve the web-pages – it was able to sustain about 70M/
s in CL vs about 15k/s in Java (I thought I was going to have a heart
attack, that’s more than 4500 times higher throughput).

What’s the point? Well, that how you do things can be pretty
important. RoR is roughly the same throughput as my java applications
have been – even using Webrick, and Mongrel is faster still –
assuming no long-running operations. Also, I still don’t do
everything in CL.


The trouble with Ruby is that there are situations where some low-
level operation is being executed so often that it becomes the
problem. For example, my XML parser string manipulation is the main
consumer of time – lots and lots of calls to pretty quick methods
(Sam R.’ example in this thread of string compares shows the
problem, string comparison can be faster than a method call, yet
still be responsible for most of your execution time). I don’t have a
solution for this. Maybe a VM will help with this but I’m not
really sure of that.

I also have my suspicions about garbage collection in Ruby. I may be
wrong to suspect GC, but you won’t need a VM to do something to speed
it up.


There are trade-offs all over the place here. And aside from using
Mongrel, I don’t think I’ve ever chosen a route (in Ruby) where
native code was involved. And that includes databases – I use a pure
Ruby thing, xampl (see link below), and don’t regret it.

Cheers,
Bob


Bob H. – blogs at <http://www.recursive.ca/
hutch/>
Recursive Design Inc. – http://www.recursive.ca/
Raconteur – http://www.raconteur.info/
xampl for Ruby – http://rubyforge.org/projects/xampl/