Android Question [SOLVED] How to speed up a For-Next loop?

Midimaster

Active Member
Licensed User
I have to calculate a lot of values in a FOR/NEXT with 8.000.000 loops. It happens each time, when the user press one of 10 buttons. Now it happens, that the user presses the button while the previous loop is still running. In this case I want, that the first loop is given up and restarts with new values. This gives the user a faster running impression.

I tried to enter a Sleep(0) command, so that the buttons can be checked during a loop is running. But this makes the loop extremly slow. so now the loop need 5 times longer than before. this makes my idea obsolet to offer the user a fast speed impression.

I added a 4th way to the code, which brought the result of 100msec! So the problem is solved.

B4X:
Sub looping
    Dim zeit As Long=DateTime.Now
    Log("waiting")
    Dim i As Int
    For i =0 To 8000000
    Next
    Log("without="& (DateTime.Now-zeit))

    zeit =DateTime.Now
    For i =0 To 8000000
        If i Mod 30000=0 Then
            'Sleep(0)
        End If
    Next
    Log("normal="& (DateTime.Now-zeit))

    zeit =DateTime.Now
    For i =0 To 8000000
        If i Mod 30000=0 Then
            Sleep(0)
        End If
    Next
    Log("with waiting="& (DateTime.Now-zeit))

    zeit =DateTime.Now
    For j =0 To 8000000 Step 30000
        Sleep(0)
        Dim bis As Int=j+30000
        If bis>8000000 Then
            bis=8000000        
        End If
        For i=j To bis
        Next
    Next
    Log("optimized waiting="& (DateTime.Now-zeit))
End Sub

The speed results are:
without=103msec
normal=150msec
with waiting=274msec
optimized=100msec


and on my old Android-4 Tablet:
without=1183msec
normal=1493msec
with waiting=2278msec
optimized=1103msec


but on a PC-"BlitzMax"-App
without=3msec
normal=37msec
with waiting=40msec

Does anybody know, what I can do to optimize a FOR/NEXT loop or interact with Events during the loop?

Another by-the-way-question: Why do I not need to define the "i" variable in FOR/NEXT? In BlitzMax I need to write:
B4X:
For Local i:INT=0 to 1000
And what is the scope of this "i"? At the moment I always add a "Dim i as INT" before writing the loop, but I don't know, if this is the best practice or necessary...
 
Last edited:

Sandman

Expert
Licensed User
Longtime User
I don't have anything real to add to your question, but I did notice that you have a bug in your time-calculating code that makes the logged values wrong. You are always using the same value for zeit. You should copy line 2 and add it at line 8 and then again at line 15, so each test gets a fresh value for that.
 
Upvote 0

Midimaster

Active Member
Licensed User
Even in the moment, when I wrote the question here I had an idea, how a solution could be... And now I added another algo which does not consume additional time. Often it already helps to get a little bit of distance to the problem.... thank you.

@agraham: the wxample code is only to demonstrate the problem dramatically. In my app I have of course divided the calculation in parts. But also here I want to save some msec's.
 
Upvote 0

sorex

Expert
Licensed User
Longtime User
(re)creating variables is time consuming and you do it inside your loop which is bad if it is not really required.

put that Dim bis As Int before the loop and it will be faster. just set the base value inside the loop. sleep has no use either there.

it's hard to optimize something that has nothing to do with the actual routine that you want to optimize.

if it is too slow and blocks/freezes your interface then go for threading.
 
Upvote 0

Sandman

Expert
Licensed User
Longtime User
Depending on the situation, which we don't know anything about really, it might also be an alternative to pre-calculate all values. Probably not, but I thought I'd mention it.
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
(re)creating variables is time consuming and you do it inside your loop which is bad if it is not really required.
To be pedantic this is not true for B4X. There is no block scoping for variables, they all have method scope, so variable declarations are hoisted out of the loop as you can see if you look at the generated Java code.
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
1) Unless Blitz Max exists for Android, those numbers are mute
2) For For loops one does not explicitly have to have the loop variable dim'ed before usage. Try it. The default declaration will be an Int
3) I think this case does not really prove anything. The way I see it
If your 8 million loops finish in 15ms, who cares?
If your 8 million loops finish in 100ms, how fast do you need user response to interrupt to be? 20ms? Then you only need 5 interruptions, not 266. That is a crazy amount of interruptions, and no wonder your loop time explodes.
If you loop takes longer than that, then the overhead of the interruptions will become less and less, and again, a mute point

So 1) Figure out how long your process actually takes (without sleep's) , 2) figure out the time interval that you think would be good enough to give the user a good experience in aborting the loop (and start a new one) and 3) insert the appropriate number of sleep(s) in the loop for that interaction. Then see how much overhead the sleep really has.
 
Upvote 0

Midimaster

Active Member
Licensed User
Thank you for all this answers.

All my experiments are because I try also to run the software on old devices (starting from android 4.4).

If the device is a new one, the code would not use this technique, of course. The 100msec only demonstrated, that the problem does not exist on newer devices.

Yes, the 100msec would be a perfect time, but on a old 4.4 tablet I needed 2450msec, which is a lot for only the loop.
My code needs aditional 2000msec on this old device... so the loop itself eats the half of the performance.

The interrupt every 30.000 iterations is given and is necessary because of other reasons.
as you see during the day I added a 4th way into the code box, which was the solution for me. This "dividing" in two FOR/NEXT loops reduced the time consuption to 1100msec on the old device. That was the target.
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
I added a 4th way into the code box, which was the solution for me.
Looks like Mod was the culprit. Not calling it 8 million times seems to help a lot (in your case). Poor Sleep(), it got all the attention!
 
Upvote 0
Top