Thursday, August 24, 2006

RealBasic loops, arrays and MemoryBlocks

(... following text is my answer to a usenet post ..)
I wrote a test function that makes various speed-checks. The number Ireport are in Rosetta emulation, but it does not matter, since they are"good enough" and the point is not to bench RB against other "native"languages, but to test RB against itself.However, running in Windows gaves about a 2x improvement respect toRosetta code.
All loops involve 1000000(10e6) iterations (double loop make 1000 * 1000iterations). I also tried with 10000000 (10e7) iterations and it tookabout 10 times more than the 1000000(10e6) iteration. That is to saybechmarks are linear with number of elements (as expected). I didn't trybigger values as it involved paging, thus making quite useless the test.
The first one is a void loop. It takes 0.09 seconds on my MacIntel. Then I made a double void loop. It takes the same time. That is to sayusing two nested for does not take more time.
Then I made a simple loop that copies a variable into another variable.This runs in 0.17 seconds. Good.The third loop puts in the variable array elements. 0.17 seconds. Thesame. So arrays are well optimized: accessing an element of an arraytakes the very same time than accessing a single variable.
I then tried using two dimensional arrays: we get to 0.22 seconds. Sothis is slower, but not a *lot* slower (even if for large objects this+33% can make the difference).
And then memory blocks. I was surprised: 0.3 seconds. It seems thatusing memory blocks is slower than using arrays (and in fact there is arationale behind this: a lot of people use arrays to store large amountsof data, they *must* be ultra optimized. I think that MemoryBlocks areused more often in a different fashion).
#pragma DisableBackgroundTasks
#pragma DisableBoundsChecking
Const LoopSize = 1000000
Const SmallerLoop = 1000
Dim void_start, void_end, arr_start, arr_end  As Double
Dim var_start, var_end, mat_start, mat_end  As Double
Dim block_start, block_end, dvoid_start, dvoid_end  As Double
Dim var As Double
Dim value As  Double = 1.0
Dim arr(LoopSize) As Double
Dim mat(SmallerLoop, SmallerLoop) As Double
Dim block As MemoryBlock

for i As Integer = 0 to UBound(arr)
    arr(i) = value
next

for i As Integer = 0 to SmallerLoop
    for j As Integer = 0 to SmallerLoop
        mat(i, j) = 1.0
    next
next

block = NewMemoryBlock(LoopSize * 8)

for i As Integer = 0 To (LoopSize-1) * 8 Step 8
    block.DoubleValue(i) = 1.0
next

void_start = Microseconds()

for i As Integer = 0 to LoopSize
next
void_end = Microseconds()
MsgBox "Void loop(" + Str(LoopSize) + "): " + Str((void_end - void_start)/1000000) 

dvoid_start = Microseconds()

for i As Integer = 0 to SmallerLoop
    for j As Integer = 0 to SmallerLoop
    next
next

dvoid_end = Microseconds()
MsgBox "Double void loop(" + Str(LoopSize) + "): " + Str((dvoid_end - dvoid_start)/1000000)

var_start = Microseconds()
for i As Integer = 0 to LoopSize
    var = value
next
var_end = Microseconds()
MsgBox "Var loop(" + Str(LoopSize) + "): " + Str((var_end - var_start)/1000000)

arr_start = Microseconds()

for i As Integer = 0 to LoopSize
    var = value
next

arr_end = Microseconds()
MsgBox "Arr loop(" + Str(LoopSize) + "): " + Str((arr_end - arr_start)/1000000)

mat_start = Microseconds()
for i As Integer = 0 to SmallerLoop
    for j As Integer = 0 to SmallerLoop
        var = mat(i, j)
    next
next

mat_end = Microseconds()
MsgBox "Mat loop(" + Str(LoopSize) + "): " + Str((mat_end - mat_start)/1000000)

block_start = Microseconds()

for i As Integer = 0 To (LoopSize-1) * 8 Step 8
    var = block.DoubleValue(i)
next

block_end = Microseconds()
MsgBox "Block loop(" + Str(LoopSize) + "): " + Str((block_end - block_start)/1000000)

block_start = Microseconds()

for i As Integer = 0 To (LoopSize-1)
    var = block.DoubleValue(i*8)
next

block_end = Microseconds()
MsgBox "Block loop(" + Str(LoopSize) + "): " + Str((block_end - block_start)/1000000)