You are on page 1of 6

Optimizing Code

Unless you're doing tasks like generating fractals, your applications are unlikely to be limited by
the actual processing speed of your code. Typically other factors — such as video speed,
network delays, or disk activities — are the limiting factor in your applications. For example,
when a form is slow to load, the cause might be the number of controls and graphics on the form
rather than slow code in the Form_Load event. However, you may find points in your program
where the speed of your code is the gating factor, especially for routines that are called
frequently. When that's the case, there are several techniques you can use to increase the real
speed of your applications:

• Avoid using Variant variables.

• Use Long integer variables and integer math.

• Cache frequently used properties in variables.

• Use module-level variables instead of Static variables

• Replace procedure calls with inline code.

• Use constants whenever possible.

• Pass arguments with ByVal instead of ByRef.

• Use typed optional arguments.

• Take advantage of collections.

Even if you’re not optimizing your code for speed, it helps to be aware of these techniques and
their underlying principles. If you get in the habit of choosing more efficient algorithms as you
code, the incremental gains can add up to a noticeable overall improvement in speed.

Avoid Using Variant Variables


The default data type in Visual Basic is Variant. This is handy for beginning programmers and
for applications where processing speed is not an issue. If you are trying to optimize the real
speed of your application, however, you should avoid Variant variables. Because Visual Basic
converts Variants to the appropriate data type at run time, operations involving other simple data
types eliminate this extra step and are faster than their Variant equivalents.

A good way to avoid Variants is to use the Option Explicit statement, which forces you to
declare all your variables. To use Option Explicit, check the Require Variable Declaration check
box on the Editor tab of the Options dialog box, available from the Tools menu.
Be careful when declaring multiple variables: If you don’t use the As type clause, they will
actually be declared as Variants. For example, in the following declaration, X and Y are variants:

Dim X, Y, Z As Long

Rewritten, all three variables are Longs:

Dim X As Long, Y As Long, Z As Long

For More Information To learn more about Visual Basic data types, see "Data Types" in
"Programming Fundamentals."

Use Long Integer Variables and Integer Math


For arithmetic operations avoid Currency, Single, and Double variables. Use Long integer
variables whenever you can, particularly in loops. The Long integer is the 32-bit CPU's native
data type, so operations on them are very fast; if you can’t use the Long variable, Integer or Byte
data types are the next best choice. In many cases, you can use Long integers when a floating-
point value might otherwise be required. For example, if you always set the ScaleMode property
of all your forms and picture controls to either twips or pixels, you can use Long integers for all
the size and position values for controls and graphics methods.

When performing division, use the integer division operator (\) if you don’t need a decimal
result. Integer math is always faster than floating-point math because it doesn’t require the
offloading of the operation to a math coprocessor. If you do need to do math with decimal
values, the Double data type is faster than the Currency data type.

The following table ranks the numeric data types by calculation speed.

Numeric data types Speed


Long Fastest
Integer
Byte
Single
Double
Currency Slowest
Cache Frequently Used Properties in Variables
You can get and set the value of variables faster than those of properties. If you are getting the
value of a property frequently (such as in a loop), your code runs faster if you assign the property
to a variable outside the loop and then use the variable instead of the property. Variables are
generally 10 to 20 times faster than properties of the same type.

Never get the value of any given property more than once in a procedure unless you know the
value has changed. Instead, assign the value of the property to a variable and use the variable in
all subsequent code. For example, code like this is very slow:

For i = 0 To 10
picIcon(i).Left = picPallete.Left
Next I

Rewritten, this code is much faster:

picLeft = picPallete.Left
For i = 0 To 10
picIcon(i).Left = picLeft
Next I

Likewise, code like this . . .

Do Until EOF(F)
Line Input #F, nextLine
Text1.Text = Text1.Text + nextLine
Loop

. . . is much slower than this:

Do Until EOF(F)
Line Input #F, nextLine
bufferVar = bufferVar & nextLine & vbCrLf
Loop
Text1.Text = bufferVar

However, this code does the equivalent job and is even faster:

Text1.Text = Input(F, LOF(F))

As you can see, there are several methods for accomplishing the same task; the best algorithm is
also the best optimization.

This same technique can be applied to return values from functions. Caching function return
values avoids frequent calls to the run-time dynamic-link library (DLL), Msvbvm60.dll.

Use Module-level Variables Instead of Static Variables


While variables declared as Static are useful for storing a value over multiple executions of a
procedure, they are slower than local variables. By storing the same value in a module-level
variable your procedure will execute faster. Note, however, that you will need to make sure that
only one procedure is allowed to change the module-level variable. The tradeoff here is that your
code will be less readable and harder to maintain.

Replace Procedure Calls with Inline Code


Although using procedures makes your code more modular, performing each procedure call
always involves some additional work and time. If you have a loop that calls a procedure many
times, you can eliminate this overhead by removing the procedure call and placing the body of
the procedure directly within the loop. If you place the same code inline in several loops,
however, the duplicate code increases the size of your application. It also increases the chances
that you may not remember to update each section of duplicate code when you make changes.

Likewise, calling a procedure that resides in the same module is faster than calling the same
module in a separate .BAS module; if the same procedure needs to be called from multiple
modules this gain will be negated.

Use Constants Whenever Possible


Using constants makes your application run faster. Constants also make your code more readable
and easier to maintain. If there are strings or numbers in your code that don’t change, declare
them as constants. Constants are resolved once when your program is compiled, with the
appropriate value written into the code. With variables, however, each time the application runs
and finds a variable, it needs to get the current value of the variable.

Whenever possible, use the intrinsic constants listed in the Object Browser rather than creating
your own. You don’t need to worry about including modules that contain unused constants in
your application; when you make an .exe file, unused constants are removed.

Pass Unmodified Arguments with ByVal Instead of ByRef


When writing Sub or Function procedures that include unmodified arguments, it is faster to pass
the arguments by value (ByVal) than to pass them by reference (ByRef). Arguments in Visual
Basic are ByRef by default, but relatively few procedures actually modify the values of their
arguments. If you don’t need to modify the arguments within the procedure, define the them as
ByVal, as in the following example:

Private Sub DoSomething(ByVal strName As String, _


ByVal intAge As Integer)

Use Typed Optional Arguments


Typed optional arguments can improve the speed of your Sub or Function calls. In prior versions
of Visual Basic, optional arguments had to be Variants. If your procedure had ByVal arguments,
as in the following example, the 16 bytes of the Variant would be placed on the stack.

Private Sub DoSomething(ByVal strName As String, _


Optional ByVal vntAge As Variant, _
Optional ByVal vntWeight As Variant)

Your function uses less stack space per call, and less data is moved in memory, if you use typed
optional arguments:

Private Sub DoSomething(ByVal strName As String, _


Optional ByVal intAge As Integer, _
Optional ByVal intWeight As Integer)

The typed optional arguments are faster to access than Variants, and as a bonus, you'll get a
compile-time error message if you supply information of the wrong data type.

Take Advantage of Collections


The ability to define and use collections of objects is a powerful feature of Visual Basic. While
collections can be very useful, for the best performance you need to use them correctly:

• Use For Each...Next rather than For...Next.

• Avoid using Before and After arguments when adding objects to a collection.

• Use keyed collections rather than arrays for groups of objects of the same type.

Collections allow you to iterate through them using an integer For...Next loop. However, the For
Each...Next construct is more readable and in many cases faster. The For Each...Next iteration is
implemented by the creator of the collection, so the actual speed will vary from one collection
object to the next. However, For Each...Next will rarely be slower than For...Next because the
simplest implementation is a linear For...Next style iteration. In some cases the implementor may
use a more sophisticated implementation than linear iteration, so For Each...Next can be much
faster.

It is quicker to add objects to a collection if you don't use the Before and After arguments. Those
arguments require Visual Basic to find another object in the collection before it can add the new
object.

When you have a group of objects of the same type, you can usually choose to manage them in a
collection or an array (if they are of differing types, a collection is your only choice). From a
speed standpoint, which approach you should choose depends on how you plan to access the
objects. If you can associate a unique key with each object, then a collection is the fastest choice.
Using a key to retrieve an object from a collection is faster than traversing an array sequentially.
However, if you do not have keys and therefore will always have to traverse the objects, an array
is the better choice. Arrays are faster to traverse sequentially than collections.

For small numbers of objects, arrays use less memory and can often be searched more quickly.
The actual number where collections become more efficient than arrays is around 100 objects;
however, this can vary depending on processor speed and available memory.

For More Information See "Using Collections as an Alternative to Arrays" in "More About
Programming."

You might also like