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