Maradék szabadidőmben ismét haszontalan dolgokkal kezdtem el foglalkozni, mint pl. a jó öreg Mandelbrot és Julia halmazok. Mivel a Ruby nyelvvel is most ismerkedem, remek alkalomnak tűnt a kettőt kombinálni.

Aztán belefutottam ebbe: http://shootout.alioth.debian.org/u64/performance.php?test=mandelbrot

Azt sejtettem, hogy a Ruby nem a legjobb választás a sima matematikai problémák megoldására - arra továbbra is a legjobb a C vagy a bátrabbaknak az Assembly - de az, hogy ilyen durván lassú legyen, azért nem gondoltam.

A leghosszabb tesztnél egy 16000x16000 pixel méretben kell előállítani az alap Mandelbrot halmazt, színek nélkül, monokróm képként. Ami C-ben 30 másodperc, az Ruby-ban 5400 másodperc, azaz 1 óra 20 perc (Ruby 1.9.2).

A probléma persze nyilvánvaló, Ruby-ban nincsenek primitívek, minden objektum, még a legegyszerűbb szám is.

irb(main):001:0> 2.object_id
=> 5
irb(main):002:0> (1+1).object_id
=> 5

Tehát mindegy hogyan jutunk el '2'-höz, az ugyanaz az objektum lesz, amíg a szám belefér a Fixnum osztályba.

Így a ciklusszervezés, ami szuper primitív kéne hogy legyen, az is brutálisan lassú lesz.

for i in 1..16000 do
for j in 1..16000 do
end
end

Ez a két egymásba ágyazott ciklus ~35 másodpercig tart, ez pont annyi idő ami alatt a C-ben írt algoritmus befejezte a teljes Mandelbrot számítást...

A probléma fokozható:

for i in 2000000001..2000016000 do
for j in 2000000001..2000016000 do
end
end

Ekkor Range-ben már nagyok lesznek az egyes számok, ezek már nem férnek bele a Fixnum class-ba, csak a Bignum class-ba, ekkor valami érdekesség történik az object_id-vel:

irb(main):067:0> 2000000001.object_id
=> 74483390
irb(main):068:0> 2000000001.object_id
=> 74462640
irb(main):069:0> 2000000001.object_id
=> 74458330

Az object_id mindig más és más. Fogalmam sincs mi megy végbe a motorháztető alatt, de bármi is legyen, a gyanúm az volt, hogy nem fogja gyorsítani a futásidőt. Ez be is jött.
A futásidő ebben az esetben már ~150 másodperc lesz, vagyis 5-szörös a Fixnum-hoz képest.

Tehát sajnos az a helyzet, hogy a Ruby teljesen alkalmatlan arra, hogy nagy méretű listák elemeivel akárcsak egyszerű műveleteket is végezzünk, mert a ciklusszervezés önmagában horribilis időveszteséget okoz.