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.
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
Next doesn't help. You can leave it, you can remove it, but you can't optimize it.
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
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.
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.
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
Replace$ does no better than
Replace$ is exactly the same as
Replace. There is no string vs. variant difference. No need to add the dollar.
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
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?
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
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.
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.
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 string handling in Visual Basic
Visual Basic tips — Optimize for memory and speed