Make faster Richards benchmark

I’d appreciate any suggestions on how to make a faster Ruby
implementation of Richards benchmark. Perhaps there are obvious
problems that can be corrected?

http://www.lissett.com/ben/bench1.htm

In article 6748553f.0405232121.1ec69094@posting.google.com,

I’d appreciate any suggestions on how to make a faster Ruby
implementation of Richards benchmark. Perhaps there are obvious
problems that can be corrected?

http://www.lissett.com/ben/bench1.htm

Have you tried the profiler on this code?

put 'require ‘profile’ at the top of the code.

This seems to be a fairly involved benchmark, so profiling it should help
to narrow down which parts of the code to concentrate your optimization
efforts on.

Check out the “When Trouble Strikes” chapter of the Programming Ruby book
(especially ‘But it’s too slow’) online here:

http://phrogz.net/programmingruby/

Phil

···

Duncan Lissett dlissett0@yahoo.com wrote:

this:
class Scheduler
@table
@list
@currentTcb
@currentId
@v1
@v2
@queueCount
@holdCount

def initialize()
@table = Array.new(MAXTASKS,nil)
@list = nil
@queueCount = 0
@holdCount = 0
end

is not what you think, I believe :slight_smile:
You can remove the @vars, at the top, leave thos in the method calls.
you don’t need to show to ruby that they’re instance variables the @
does this already :slight_smile:

then remove the useless (). And the useless 'then’s and 'return’s

Next, I believe you could use attr_accessor for many variables.
And use a Task superclass will make the code much shorter I believe :slight_smile:

Using Array.at(someIndex) is slightly faster than array[someIndex].

And I believe there is a linked list to handle a queue that probably
could be replaced from a normal Array.

Anyway, I believe that code should be rewritten from the specs, more
than just ‘ported’ from some other language.
hope this helps.

···

il 23 May 2004 22:21:12 -0700, dlissett0@yahoo.com (Duncan Lissett) ha scritto::

I’d appreciate any suggestions on how to make a faster Ruby
implementation of Richards benchmark. Perhaps there are obvious
problems that can be corrected?

http://www.lissett.com/ben/bench1.htm

The uselessness of these is highly subjective.

Parens after method calls and method definitions, ‘then’, and ‘return’
are purely cosmetic, and do not change execution speed.

···

gabriele renzi (surrender_it@rc1.vip.ukl.yahoo.com) wrote:

il 23 May 2004 22:21:12 -0700, dlissett0@yahoo.com (Duncan Lissett) ha
scritto::

I’d appreciate any suggestions on how to make a faster Ruby
implementation of Richards benchmark. Perhaps there are obvious
problems that can be corrected?

then remove the useless (). And the useless 'then’s and 'return’s


Eric Hodel - drbrain@segment7.net - http://segment7.net
All messages signed with fingerprint:
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

gabriele renzi surrender_it@remove.yahoo.it wrote in message news:6293b0lbejdddpv4rqnvh3sljfsuppc8ha@4ax.com

You can remove the @vars, at the top, leave thos in the method calls.
then remove the useless (). And the useless 'then’s and 'return’s

Thanks - the returns aren’t useless :wink:

Next, I believe you could use attr_accessor for many variables.
And interestingly that makes things somewhat faster.

And use a Task superclass will make the code much shorter I believe :slight_smile:
Yes, I just like to demonstrate the lack of superclass or interface.

Using Array.at(someIndex) is slightly faster than array[someIndex].
Yes, it is.
Using integer literals instead of constants made things a little
faster too.

And I believe there is a linked list to handle a queue that probably
could be replaced from a normal Array.
It could, but it seems to be ~10% slower

Anyway, I believe that code should be rewritten from the specs, more
than just ‘ported’ from some other language.

I’d certainly be interested in seeing other implementations - there
are procedural implementations at
http://www.lissett.com/ben/bench3.htm

Seems like Ruby shows best with an OO style implementation
http://www.lissett.com/ben/bench1.htm

Phil, Gabriele, thanks for those suggestions.

Nice that we are now faster than python, but there is still room for
small improvements.
You can find my version here:

http://flwrpwr.free.fr/Ruby/bench/bench27.rb

It is based on version #26 of the ruby OO bench, with the following
changes:

  • precompile the isHeldOrSuspended? expression (this gives the
    largest speed gain)
  • use
    @state |= x
    instead of
    @state = @state | x
    (it is slightly faster)
  • remove unneeded temporary variables and unused return values
  • rewrite some conditionals in a more rubyish way (and more efficient)
  • make better use of conditionals return value (eg like in Tcb.run)
  • use symbols to represent packet kind. (this is more a style change,
    speed is unchanged)
  • in WorkerTask.run, use collect! to change the content of packet.a2

The speed gain between my version and #26 is approximatelly the same
as between #26 and #25.

Bye bye

Denis

igouy@yahoo.com (Isaac Gouy) wrote in message news:ce7ef1c8.0405241603.787e1004@posting.google.com

Seems like Ruby shows best with an OO style implementation
http://www.lissett.com/ben/bench1.htm

Well I haven’t tried a procedural implementation in Ruby.
Isaac thanks for the comments.

another little thing:
maybe using the ugly c-ish ternary op instead of if…then…else in
tcp.initialize may bring something ? (I see it in other places).

Also, I know asyntotically it’s irrelevant, but maybe using one single
print statement with sharp-braket interpolation in main() may bring
something, and You should be able to replace Proces.times.utime with
Time.now, dunno if it gains something.
Just to go ander 100 :slight_smile:

···

il 25 May 2004 04:59:27 -0700, dmertz@free.fr (denis) ha scritto::

Nice that we are now faster than python, but there is still room for
small improvements.
You can find my version here:

http://flwrpwr.free.fr/Ruby/bench/bench27.rb

It is based on version #26 of the ruby OO bench, with the following
changes:

dmertz@free.fr (denis) wrote in message news:4d8bbb4a.0405250359.90392a1@posting.google.com

Nice that we are now faster than python, but there is still room for
small improvements.
You can find my version here:
http://flwrpwr.free.fr/Ruby/bench/bench27.rb

Thanks for taking a careful look at what could be done.

  • precompile the isHeldOrSuspended? expression (this gives the
    largest speed gain)

If we convert those boolean conditions to a table lookup then we
should do the same in the other language implementations - so although
it’s a nice optimization I haven’t used it.

(You’ll probably notice there are still a couple of “mistakes” where
code could be simplified - the same mistakes exist in the other
language implementations, so they’ll have to wait until I feel like
changing all the implementations.)

  • use
    @state |= x
    instead of
    @state = @state | x
    Good catch.
  • rewrite some conditionals in a more rubyish way (and more efficient)
    zero? Good.
  • make better use of conditionals return value (eg like in Tcb.run)
    I understand we could do that, it doesn’t seem as readable to me so I
    wouldn’t.
  • use symbols to represent packet kind. (this is more a style change,
    speed is unchanged)
  • in WorkerTask.run, use collect! to change the content of packet.a2
    Thanks, a newbie like me would never have found that.

The speed gain between my version and #26 is approximatelly the same
as between #26 and #25.

The more limited changes I’ve taken from your example make #28 ~0.7s
faster.

Duncan Lissett wrote:

  • precompile the isHeldOrSuspended? expression (this gives the
    largest speed gain)

If we convert those boolean conditions to a table lookup then we
should do the same in the other language implementations - so although
it’s a nice optimization I haven’t used it.

How about changing
(@state & 0b100) != 0 || @state == 0b10
to
@state == 0b10 || (@state & 0b100) != 0
instead?

That shows a 4% gain in overall speed here. Enough to get below 100? :wink:

Also, though I think the ternary operator is actually more readable than
an “if” in assignments, using it in WorkerTask#run only improved the
time by 0.5% - probably well within the standard deviation.

Isn’t the point of the benchmark to compare straightforward code that
can be reasonably be said to be equivalent in all the various languages?

martin

···

Duncan Lissett dlissett0@yahoo.com wrote:

dmertz@free.fr (denis) wrote in message news:4d8bbb4a.0405250359.90392a1@posting.google.com

Nice that we are now faster than python, but there is still room for
small improvements.
You can find my version here:
http://flwrpwr.free.fr/Ruby/bench/bench27.rb

Thanks for taking a careful look at what could be done.

Martin DeMello wrote:

dmertz@free.fr (denis) wrote in message news:4d8bbb4a.0405250359.90392a1@posting.google.com

Nice that we are now faster than python, but there is still room for
small improvements.
You can find my version here:
http://flwrpwr.free.fr/Ruby/bench/bench27.rb

Thanks for taking a careful look at what could be done.

Isn’t the point of the benchmark to compare straightforward code that
can be reasonably be said to be equivalent in all the various languages?

I wouldn’t think so. If you’re benchmarking languages rather than
algorithms, I think the intent should be to implement the benchmark
using best practices for each of the language. I’ve seen too many
benchmarks where people wrote FORTRAN in half a dozen languages, never
touching the features or design approaches actually practiced by users
of the other languages.

–paul

···

Duncan Lissett dlissett0@yahoo.com wrote:

Martin DeMello martindemello@yahoo.com wrote in message news:m4ftc.603356$Ig.361204@pd7tw2no

Nice that we are now faster than python, but there is still room for
small improvements.
You can find my version here:
http://flwrpwr.free.fr/Ruby/bench/bench27.rb

Thanks for taking a careful look at what could be done.

Isn’t the point of the benchmark to compare straightforward code that
can be reasonably be said to be equivalent in all the various languages?

Martin, I don’t understand what point you’re making - spell it out for
me.

There is one obvious difference between the language implementations -
the Smalltalks, Pythons, and Ruby use numeric literals in the Tcb
class. That’s pretty questionable :wink: (Other differences are probably
unintended.)

Mostly that the more clever optimisation we use, the harder it’s going
to be to separate “ruby benchmarks better than python does” from “the
ruby guys did a better job of implementing this than the python guys
did”. OTOH the fact that it’s easier to do a better implementation in
ruby may be more significant than the raw speed of the interpreter :slight_smile:

martin

···

Duncan Lissett dlissett0@yahoo.com wrote:

Martin DeMello martindemello@yahoo.com wrote in message news:m4ftc.603356$Ig.361204@pd7tw2no

Nice that we are now faster than python, but there is still room for
small improvements.
You can find my version here:
http://flwrpwr.free.fr/Ruby/bench/bench27.rb

Thanks for taking a careful look at what could be done.

Isn’t the point of the benchmark to compare straightforward code that
can be reasonably be said to be equivalent in all the various languages?

Martin, I don’t understand what point you’re making - spell it out for
me.

Martin DeMello martindemello@yahoo.com wrote in message news:XFVtc.579069$Pk3.488631@pd7tw1no

Mostly that the more clever optimisation we use, the harder it’s going
to be to separate “ruby benchmarks better than python does” from “the
ruby guys did a better job of implementing this than the python guys
did”. OTOH the fact that it’s easier to do a better implementation in
ruby may be more significant than the raw speed of the interpreter :slight_smile:

Broadly, I agree.

The differences due to implementation ‘style’ (OO & Original) are also
interesting to me. Does the language even allow a non-OO approach?
Does the type system get in the way?

All good, clean, fun :wink: