How not to optimize in Visual Basic
Optimizing Visual Basic 6.0 code can be fun or tedious, depending on the way you look at it. Here are some pitfalls to avoid when optimizing.
Just remember, this article shows how not to program.
For
loops
Let's start with a pitfall we fell into.
For i = LBound(arr) To UBound(arr)
Total = Total + arr(i)
Next i
Does the above code look unoptimized? Shouldn't you rewrite it like this:
Dim LB As Long, UB As Long
LB = LBound(arr)
UB = UBound(arr)
For i = LB To UB
Total = Total + arr(i)
Next
There is no difference. Optimizing what's displayed in red isn't going to help you much. The start and final values of a For statement are evaluated only once, at the start of the For loop. They are not evaluated at each loop iteration.
What is more, leaving out the i
after Next
doesn't help. You can leave it, you can remove it, but you can't optimize it.
If
statements
When you put an If..Then
statement on one line, you gain speed, right?
If condition Then statement
Not true. Using the multiline variant is as fast, but often more readable.
If condition Then
statement
End If
OK. How about the conditions then? Assume that i is a non-negative integer. It can be 0, 1, 2 etc. but not below zero. Then, assume you want to test if i contains a positive number.
Which one would you use to test for that: i > 0
or rather i <> 0
? One could think that since i is never negative, <>
is an unnecessarily complex operator and makes no sense. Replacing it with just >
looks promising. But it turns out that i <> 0
is faster. Oh, these computers make me mad!
Unoptimal string optimization
Case-insensitive StrComp
is for sorting, not for testing
You might think that StrComp(,, vbTextCompare)
would be an ideal way to handle case-insensitive comparison. It is not, however, because this way you're subject to bugs. StrComp
with vbTextCompare
(or Option Compare Text
) does more than just case-insensitive compare. Strings that don't match literally may compare equal. For example, ae matches the ligature ć. Depending on what you want, this may be desired or undesired in your application. But it isn't pure case-insensitive compare.
Also beware than StrComp(,, vbTextCompare)
may work differently under different locales (regional settings). Your program might fail under a locale you haven't tested in.
StrComp
is best left for sorting. It's not the best function to compare for equality.
Don't Like
The Like
operator looks handy—and it is. Unfortunately it's slow too. Avoid it if you can. Use your imagination with the other string functions, including AscW
, Left$
, Len
etc.
Replace$
does no better than Replace
Replace$
is exactly the same as Replace
. There is no string vs. variant difference. No need to add the dollar.
No InputB$
Did you think all byte functions are fast as lightning? Not InputB$
. If you need to load in a large file, try some other way.
Data types, objects, variables, arrays
Don't Dim .. As New
Dim obj As MyClass
Set obj = New MyClass
Why write 2 lines when you can just say Dim obj As New MyClass
?
Never Dim
anything As New
if you're concerned about speed. VB6 will treat such a variable as an auto-instantiated variable. Every time you use it, VB will check if it should be instantiated. This will cost you some extra CPU cycles.
Numeric data types
Bytes, Booleans and Integers use less memory than Longs. That's true. However, they're not faster. Windows is 32-bit and so are Longs. If you need the utmost speed, use Longs.
Static
makes your app sooo static
Did you know that Static
local variables are slower than the normal Dim
locals? One could think that Static
variables are faster as they don't need to get allocated every time you call the procedure. But it's not so. Use Dim
unless you have to do Static
.
Incremental ReDim Preserve
You might be tempted to use the following code to allocate more space for an array.
ReDim Preserve myarray(UBound(myarray) + 1)
This code allocates one more entry for myarray when required, keeping the array size as small as possible. This may work well for small arrays. If you repeatedly execute this line and myarray becomes large, your application locks up every time you allocate more space. It's better to allocate in larger chunks.
If arrayindex > UBound(myarray) Then
ReDim Preserve myarray(UBound(myarray) + 1000)
End If
This way you allocate some more entries if you go out of space. +1000 is just an example. You should consider which chunk size suits your application best. Try doubling the size, for example. Or you could start with one chunk size, and adjust the size as the array grows.
With
blocks
You've probably heard that replacing a.b.c.d
style references with With a.b.c
can benefit you.
Did you actually measure the effect? A With block isn't always the fastest alternative. It depends on what expressions you use and how many calls you save. Adding a With block for 1 or 2 calls is probably not worth it.
Don't Bang!Bang
The bang (!) operator can lead to late binding. Although your code looks short and optimized, it runs slowly. Try the alternatives, if you have any.
A word about those DLLs and OCXs
VB is slow. Other languages are fast. You get better performance withs DLLs, OCXs and as little VB code as possible.
Wrong! Stay away from extra run-times unless you know what you're doing. You can often write the same functionality in pure VB. This way you not only save the distribution of the run-times, but your code might actually execute faster. Don't take our word for it. Get VB Watch Profiler and time your code.
More optimization readings
Optimize loops
Optimize string handling in Visual Basic
Visual Basic tips — Optimize for memory and speed