Page 1 of 1

"Smart" For?

Posted: Sun Jan 26, 2025 12:47 am
by Piero

Code: Select all

k=2
For i=1 To k
   Debug i
   k-1 ; exits For earlier
Next

s.s="N2"
For i=1 To Len(s)
   Delay(1) ; s unchanged
Next
Is the compiler "smart" enough to make it calculate Len(s) only once?

Re: "Smart" For?

Posted: Sun Jan 26, 2025 1:48 am
by BarryG
It's by design (previous discussion on this forum somewhere). The Len() bit is recalculated with every loop iteration, for times when it can change by the coder (which is a valid use case). But if it's a static value that never changes, then for speed it's better to assign it to a variable and use the variable in the "For" statement.

Re: "Smart" For?

Posted: Sun Jan 26, 2025 1:58 am
by Piero
Yep, thanks! I just tested it:

Code: Select all

For i=1 To 10000
   s.s+"."
Next
n=Len(s)

StartTime.q = ElapsedMilliseconds()
For i=1 To Len(s)
   Delay(1)
Next
Debug ElapsedMilliseconds() - StartTime ; 11650

StartTime = ElapsedMilliseconds()
For i=1 To n
   Delay(1)
Next
Debug ElapsedMilliseconds() - StartTime ; 11451 (0.2 secs faster)

Re: "Smart" For?

Posted: Sun Jan 26, 2025 9:16 am
by STARGÅTE
Piero wrote: Sun Jan 26, 2025 1:58 am Yep, thanks! I just tested it:
That's not how to test properly.
Time measurements have to be performed always with disabled debugger.
Delay() is not time critical. Delay(1) not always waits exact 1 ms!

Here a test code that shows, how many times the loop condition is called:

Code: Select all

Procedure CallMy(Value.i)
	Debug "is called"
	ProcedureReturn Value
EndProcedure

Define I.i

For I = 1 To CallMy(5)
	Debug "loop content"
Next

Re: "Smart" For?

Posted: Sun Jan 26, 2025 10:58 am
by Piero
STARGÅTE wrote: Sun Jan 26, 2025 9:16 amThat's not how to test properly.
TY again!
Anyway I tested each "version" repeatedly, and results varied only very slightly…
I also tested using other loops instead of Delay.
I hoped that in very simple cases (e.g., calling a proc is not a very simple one) "optimization" could happen…

Weirdly, enabling "thread safe" seems to improve it! :shock:
But I just quickly tested now (on Mac ARM) out of pure curiosity, with Debugger and Delay :oops:

Edit/Note:
Please forgive me @STARGÅTE ; I wrote "TY again" thinking you had answered before, so I need to apologize with @BarryG too :oops: :oops:

Re: "Smart" For?

Posted: Mon Jan 27, 2025 6:35 am
by idle
compile without debugger

Code: Select all

For i=1 To 50000
   s.s+"."
Next
n=Len(s)

StartTime.q = ElapsedMilliseconds()
For i=1 To Len(s)
   a = n * i 
Next
et = ElapsedMilliseconds() - StartTime ; 11650

StartTime = ElapsedMilliseconds()
For i=1 To n
   a = n * i 
Next
et1 = ElapsedMilliseconds() - StartTime ; 11451 (0.2 secs faster)

out.s = "t1 = " + Str(et) + " t2= " + Str(et1) 
MessageRequester("times",out) 


Re: "Smart" For?

Posted: Mon Jan 27, 2025 10:03 am
by Piero
Idle with your example I would have to use an enormous string and wait hours for "et1" to be > 0, or get an overflow before :lol:

Seems that your "For i=1 To n" loop gets enormously optimized, also by the hardware (ARM)

Anyway there was no difference now in "et" (1st loop) with thread safe on

Re: "Smart" For?

Posted: Mon Jan 27, 2025 10:28 am
by idle
The loop with len(s) is walking the string each time and it won't get optimized out by the compiler, but when you time the loop with delay(1) that's what your going to get is the time for delay 1ms, not the time it takes to do the len(s) thats probably due to out of order execution.

Re: "Smart" For?

Posted: Mon Jan 27, 2025 11:14 am
by Piero
Resuming:

ALWAYS USE A NUMBER OR VARIABLE IN LOOPS IF POSSIBLE :wink:

Re: "Smart" For?

Posted: Mon Jan 27, 2025 8:27 pm
by idle
Piero wrote: Mon Jan 27, 2025 11:14 am Resuming:

ALWAYS USE A NUMBER OR VARIABLE IN LOOPS IF POSSIBLE :wink:
Yes. I was just trying to explain why you didn't see a big time difference with the delay(1) in the loop.