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