brabuhr / gmail.com wrote:
> I took a quick shot w/ duby-inline.
...
> ruby 1.8.7 (2010-01-10 patchlevel 249) [i486-linux]
>        user     system      total        real
>   18.210000   0.040000  18.250000 ( 21.596111)
...
> jruby 1.5.0 (ruby 1.8.7 patchlevel 249) (2010-05-12 6769999) (OpenJDK
> Server VM 1.6.0_18) [i386-java]
>    0.208000   0.000000   0.208000 (  0.208000)

That is a very impressive speed-up!

I see a more modest improvement going from the same original code (on
different hardware of course) to a version written in redshift. Of
course, redshift is using a more accurate integration algorithm (with 4
substeps instead of 1). Plus there are costs for the availability of
other features that are not being used in this example (e.g., a layer of
function pointers so that variables can switch to different equations
when a discrete state change occurs).

\$ ruby bench-rb.rb
user     system      total        real
evolve 6s     0.710000   0.160000   0.870000 (  0.881276)
evolve 600s  15.320000   1.010000  16.330000 ( 16.366811)

\$ ruby bench-rs.rb
user     system      total        real
evolve 6s     0.020000   0.000000   0.020000 (  0.025213)
evolve 600s   1.170000   0.000000   1.170000 (  1.178752)

\$ ruby -v
ruby 1.8.7 (2010-01-10 patchlevel 249) [x86_64-linux]

Here are the sources:

\$ cat bench-rb.rb
G = 9.8

def velocity(c, m, t, dt, vi)
t += dt
steps = t/dt

i = 0
while i < steps
v = vi
vi = v + ( G - c/m*v) * dt
i += 1
end

vi
end

require 'benchmark'
Benchmark.bm(12) do |b|
b.report("evolve 6s") do
100000.times do
velocity(0.5, 21.6, 6.0, 10.0, 0.0)
# Note: I changed the t and dt to floats for a more direct
# comparison with redshift, which uses floats for time values
end
end
b.report("evolve 600s") do
100000.times do
velocity(0.5, 21.6, 600.0, 10.0, 0.0)
end
end
end

\$ cat bench-rs.rb
require 'redshift'

class Thing < RedShift::Component
continuous :v
constant :m, :c, :G

flow do
differential " v' = G - c/m * v "
end
end

def make_world(n)
RedShift::World.new do |world|
world.time_step = 10.0
n.times do
world.create Thing do |thing|
thing.m = 21.6
thing.c = 0.5
thing.v = 0
thing.G = 9.8
end
end
end
end

require 'benchmark'
Benchmark.bm(12) do |b|
n = 1000
reps = 100
# Note: instead of 100000 sequential runs, this benchmark is doing
# 100 sequential runs of 1000 parallel instances of the same
# integration problem, which is more typical of the conditions
# redshift is optimized for

world = make_world(n)
b.report("evolve 6s") do
reps.times do
world.evolve 6.0
end
end

world = make_world(n)
b.report("evolve 600s") do
reps.times do
world.evolve 600.0
end
end
end