VBspeed / Language / For ... Next
VBspeed © 2000-10, updated: 10-Oct-2000
For ... Next


For ... Next
  1. Next or Next i ... what's faster?
  2. What loops quicker: a 2-byte Integer or a 4-byte Long?
  3. How does compiler option Integer Overflow Check affect performance?
Code
It's tricky to set up a speed test for ForNext loops:
  • ForNext loops are extremely fast and any code inside the loop is likely to take much more time than the looping itself und thus covers the differences we are looking for. Omitting any in-loop code, however, is no good solution either: if Integer Overflow Check is turned ON we do get a stable ratio between the number of loops and the time it takes to complete them, but what we measuring there is the Integer Overflow Check, not the increment of the loop counter itself. If Integer Overflow Check is turned OFF, the compiler appears to drop the whole loop if it sees no in-loop code, thus optimizing our test into nirvana.
  • Another problem arises from codespit-alignment: since we are looking for very short time differences access time to the executed code in memory becomes significant, and access time also depends on the code's alignment. Unfortunately, you cannot directly control how the compiler aligns the code -- it's a matter of good or bad luck. Inserting a dummy line somewhere before the tested part of the code can change the alignment in significant but unpredictable ways. So, it's absolutely possible that an additional line of code can speed up a procedure!
  • After hundreds of tests i finally found a piece of in-loop code that's (a) very fast, and (b) is not optimized by the compiler irrespective of the compiler options setup:
    If fFoo Then lFoo = lFoo + 1
    where fFoo and lFoo are public variables.
The timed code now looks like this (there are two nested loops to allow the Integer test to run a million times without overflowing):
Public fFoo As Boolean
Public lFoo As Long

Public Sub [IntNext|IntNextI|LongNext|LongNextI]() Dim i As [Integer|Long], j As [Integer|Long] For i = 1 To 1000 For j = 1 To 1000 If fFoo Then lFoo = lFoo + 1 Next [j] Next [i] End Sub
Calls
1Integer Overflow Check OFF, fFoo = False
2Integer Overflow Check OFF, fFoo = True
3Integer Overflow Check ON, fFoo = False
4Integer Overflow Check ON, fFoo = True
 VB5 Charts
Code
Integer Next
Integer Next i
Long Next
Long Next i
Call 1
21.0014,444Ás
31.0014,429Ás
11.0014,408Ás
41.0014,468Ás
Call 2
41.0011,586Ás
31.0011,557Ás
21.0011,551Ás
11.0011,542Ás
Call 3
42.5028,861Ás
32.5028,839Ás
11.0011,558Ás
21.0011,564Ás
Call 4
32.0025,972Ás
42.0025,981Ás
21.0013,024Ás
11.0012,969Ás
 VB6 Charts
Code
Integer Next
Integer Next i
Long Next
Long Next i
Call 1
21.0014,424Ás
41.0014,464Ás
11.0014,417Ás
31.0014,443Ás
Call 2
41.0011,583Ás
21.0011,550Ás
11.0011,542Ás
31.0011,565Ás
Call 3
32.5028,834Ás
42.5028,870Ás
11.0011,543Ás
21.0011,553Ás
Call 4
42.0025,926Ás
32.0025,930Ás
11.0012,989Ás
21.0013,029Ás
Conclusions
  • Despite all rumors: Next or Next i does NOT matter at all!! The minimal differences you see in the timings above are totally insignificant: you could produce any possible ranking order by running the same test over and over again long enough.
  • What does matter though is whether you set compiler option Integer Overflow Check OFF or ON:
    (a) when checking is OFF, Integer or Long does not affect performance. Interestingly, when the fFoo flag is True (Call 2) the code runs faster although more work is done. The only explanation i have for this is that True-conditions are processed faster than False-conditions. Or, rather, it sometimes looks that way because in a false condition, the instruction pointer has to bounce to another location in memory. And memory jumps are invariably slow.
    (b) when checking is ON, Integer loops take about two times longer than with checking OFF, which is no surprise. They also take 2 (resp. 2.5) times longer than Long loops, which can only mean that the overflow checking for Integer variables is a more complex task than for Long variables. Things become weird with Long and fFoo = False (Call 3): they process faster than with checking OFF (Call 1), which i cannot explain. When the fFoo flag is True (Call 4), they perform a bit slower than with checking OFF (but the slow-down is clearly smaller than with Integer loops).
  • Things are the same for VB5 and VB6.
The bottom line is:
  1. Do or do not repeat loop counters in the Next statement -- it's just a matter of taste and does not affect speed (and it would be a miracle if it did: both alternatives generate identical code in the executable).
  2. To be on the safe side (irrespective of compiler settings) always use Long variables as loop counters. Remember, however, that ForNext loops are very fast anyway: the possible speed gains are minimal in absolute terms and become practically irrelevant whenever the code executed within the loop is heavier than just a simple line, or when the loop is excuted only a few thousand times.
  3. A by-product of the tests above: True-conditions perform faster. So, if you can make assumptions about your conditions, set up the code so that the test returns True.
Got comments? How to read all those numbers

top




VBspeed © 2000-10 by Donald Lessau