The Stupid Things We Do

wonder

Expert
Licensed User
Longtime User
I have recently taken a whole different approach in my coding style, I used to do stupid things like this...

Old approach (stupid):
B4X:
'This is not real code, just the quickest example I could come-up with in Notepad++
Dim sizeX    = 280      As Int
Dim sizeY    = 480      As Int
Dim gridSize =  10      As Int

For x = 0 To (sizeX - 1)
    For y = 0 To (sizeY - 1)
        Dim pX = (x * gridSize) + (gridSize / 2) As Float 'Why, why, why??? LoL!!!
        Dim pY = (y * gridSize) + (gridSize / 2) As Float
        DrawCircle(pX, pY, gridSize / 2)
    Next
Next

New approach:
B4X:
'Initialization
Dim sizeX    = 280              As Int
Dim sizeY    = 480              As Int
Dim gridSize =  10              As Int

'Cache
Dim lastX        = sizeX    - 1 As Int
Dim lastY        = sizeY    - 1 As Int
Dim halfGridSize = gridSize / 2 As Float
Dim pX, pY                      As Float

'Main Cycle
For x = 0 To lastX
    pX = (x * gridSize) + halfGridSize 'There's no need to repeat this calculation 480 times in the Y cycle! Duh!
    For y = 0 To lastY
        pY = (y * gridSize) + halfGridSize
        DrawCircle(pX, pY, halfGridSize)
    Next
Next

Even better:
B4X:
'Initialization
Dim gridSize =  10                 As Int
Dim sizeX    = 280 / gridSize      As Int
Dim sizeY    = 480 / gridSize      As Int

'Cache
Dim halfGridSize = gridSize / 2           As Float
'There's no need to cache lastX and lastY for the For cycle.
'If you're using a Do While Loop Until cycle however, it's a different story.

'Main Cycle
For x = halfGridSize To (sizeX * gridSize) Step gridSize
    For y = halfGridSize To (sizeY * gridSize) Step gridSize
        DrawCircle(x, y, halfGridSize) 'Only one instruction, whoohooo!!!
    Next
Next

I won't deny that both the second and third approaches looks uglier, but this kind of approach (caching!) does perform a lot faster, especially when scaled by orders of magnitude. In my current project, this kind of clean-up lowered my cycle time from ~0.32ms to ~0.27ms. :)


For want of a nail the shoe was lost.
For want of a shoe the horse was lost.
For want of a horse the rider was lost.
For want of a rider the message was lost.
For want of a message the battle was lost.
For want of a battle the kingdom was lost.
And all for the want of a horseshoe nail.
 
Last edited:

andymc

Well-Known Member
Licensed User
Longtime User
On a similar note, is it still worth cached the results of trig functions like sin and tan in arrays anymore like in the old days??? Games used to do this as calling an array element between 0 adn 359 was quicker than calculating the Sin of 340 for each frame of the game.
 

ilan

Expert
Licensed User
Longtime User
this code gives me the correct amount of drawn circle and i get the same speed (maybe faster)

B4X:
For x = 0 To sizeX-1 'Step gridSize
    For y = 0 To sizeY-1 'Step gridSize
        c.DrawCircle(x*gridSize, y*gridSize, halfGridSize, fx.Colors.Green,False,2)
        count = count + 1
    Next   
Next

log

2.505sec
134400
 

wonder

Expert
Licensed User
Longtime User
Just tested in B4J, here's the code for the standard 600x400 window:
B4X:
'Initialization
Dim sizeX    =  60                        As Int
Dim sizeY    =  40                        As Int
Dim gridSize =  10                        As Int

'Cache
Dim halfGridSize = gridSize / 2           As Float
'There's no need to cache lastX and lastY for the For cycle.
'If you're using a Do While Loop Until cycle however, it's a different story.

'Main Cycle
For x = halfGridSize To (sizeX * gridSize) Step gridSize
    For y = halfGridSize To (sizeY * gridSize) Step gridSize
        cvs.DrawCircle(x, y, halfGridSize, fx.Colors.Red, True, 0) 'Only one instruction, whoohooo!!!
    Next
Next

Better init:
B4X:
'Initialization
Dim gridSize = 10                        As Int
Dim sizeX    = cvs.Width / gridSize      As Int
Dim sizeY    = cvs.Height / gridSize     As Int

@ilan, code corrected in the first post. Thanks for analyzing... :)
 
Last edited:

ilan

Expert
Licensed User
Longtime User
ok the "-1" was the mistake in your code

old:

B4X:
For x = halfGridSize To ((sizeX - 1) * gridSize) Step gridSize
    For y = halfGridSize To ((sizeY - 1) * gridSize) Step gridSize
        DrawCircle(x, y, halfGridSize) 'Only one instruction, whoohooo!!!
    Next
Next

new:
B4X:
For x = halfGridSize To (sizeX * gridSize) Step gridSize
    For y = halfGridSize To (sizeY * gridSize) Step gridSize
        cvs.DrawCircle(x, y, halfGridSize, fx.Colors.Red, True, 0) 'Only one instruction, whoohooo!!!
    Next
Next

but why not use the simple way?
the speed is the same
 

wonder

Expert
Licensed User
Longtime User
Like I said, it was just an example I came-up with in Notepad.

If you have a game with lots of loops (and some of them nested), this kind of optimization (caching, simplifying and pre-calculating stuff) can really help you.

Also have a look at this: https://www.b4x.com/android/forum/threads/for-vs-while.70615/
 
Top