This question is very large as a lot of it depends on the situatation. However, it is good to begin with some facts about the VB6 and how it works.
VB6 does a lot for you automatically. You don't need to think about the "hidden" background stuff, such as memory allocation, datatype conversions and coercion and so on, unless you want to. If you want to make your code efficient and fast, you need to know about the background stuff and how to let you have more control of the things that happen. Many have the image that VB6 is really slow, when they really haven't ever tried to code in the "traditional" way with it. For example, many C/C++ coders tend to use the "easy" VB style of coding and forget completely about what they know of speed and efficiency from the C/C++ world.
By default, all variables are declared as variants unless you explicitly define a different datatype. Variants are very handy and easy to use as you can do almost anything to them and they still work, but there are times when they don't work as expected. And from optimization point of view, variants are very, very slow. This is why you should always use the correct datatype.
Below is a common mistake related to variants in VB6:
' the wrong way:
Dim A, B C As Long
' only C is declared as long, A and B are variants
' the correct way:
Dim A As Long, B As Long, C As Long
' this behavior has been changed in VB.NET
Long story short: avoid using variants unless you really need them. And you rarely do.
Strings in Visual Basic are easy to handle as well. VB does a lot for you to make your life easier, but this makes strings slow as a lot of automatical processing is done in the background code. If you need to handle a lot of data, consider using an array instead. Without using any API, you can use byte arrays to convert back and forth between a string and an array:
Dim barTemp() As Byte, strTemp As String
' set something to the string
strTemp = "I am funny."
' copy string contents to a byte array
barTemp = strTemp
' show some interesting stuff in the immediate window
Debug.Print "First byte:" & barTemp(0)
Debug.Print "Second byte: " & barTemp(1)
Debug.Print "Third byte: " & barTemp(2)
Debug.Print "Lower bound: " & LBound(barTemp) & ", upper bound: " & UBound(barTemp)
' (if you do not understand how Debug.Print works, replace Debug.Print with MsgBox)
' (or View > Immediate Window to make the Debug visible)
' convert byte array to string:
strTemp = CStr(barTemp)
As you see from the example above, there is an interesting fact behind the strings: each character is actually two bytes long! However, when you read a file using Input and Output, or pass a string to API, the strings are automatically converted back to ANSI. Thus if you're handling Unicode, you want to use a byte array or an integer array.
As told before, VB does a lot of automatical stuff for you. One of these features is datatype coercion: VB automatically changes datatype to appropriate one if you pass a wrong datatype. It doesn't allow this everywhere (as with custom built procedures), but it is a problem never-the-less. Whenever possible, to gain the most speed, you should use the appropriate datatype against another similar datatype. If you need to compare or use different datatypes together, you can (and should) use the inbuilt conversion routines:
CBool, CByte, CInt, CLng, CCur, CSng, CDbl, CStr
There are more, but these are what you probably need the most. On some cases, coercion can cause unexpected errors, such as when numbers in string format are combined, they add up in a string form and not as numbers (ie. 1 + 2 = 12 and not 3). This is a problem with variants as well.
To help you use the correct datatypes and avoid many bugs and problems related to datatypes and coercion, use Option Explicit in the beginning of each form, module etc. You can make this automatical by ticking Tools > Options... > Require Variable Declaration. This will make sure you have Option Explicit in any new code element you add to your project. You have to add Option Explicit manually to any existing
There isn't much to actually optimize in the arrays, but it is very important that you check for the bounds of the arrays when you use them. This allows you to use Advanced Optimizations. And due to popular unknowledge, this is how you can check if a variable size array is declared or not:
Dim barTemp() As Byte
If (Not barTemp) = True Then MsgBox "The array is empty!"
If Not ((Not barTemp) = True) Then MsgBox "The array contains something!"
Another important note about arrays is that they work remarkably faster when the code is compiled and even more so if you enable Advanced Optimizations.
One imporant side note about arrays: one dimensional arrays are way faster than multidimendional arrays. So if you need speed, you better use a one dimensional array. Also, zero based arrays are faster than one based arrays. You should never use Option Base 1 unless you have a very good reason for it.
These are compilation options that affect the compiled code. By enabling these options (actually you are ripping off features), you can speed up your compiled code a whole lot. This requires, however, you to avoid the use of "easy" coding style VB provides. Many aspects of compiled VB code speed up close or equal to their C/C++ version of the code. VB6 compiler is actually a hacked C compiler. Please note that VB6 compiler can't of course compete with more advanced highly optimized compilers, but you do get most stuff done just as fast as you need it to.
To use the advanced optimizations, see Project > (Project name) Properties... > Compile, Advanced Optimizations...
A note about the other compile options: Favor Pentium Pro makes no difference in modern processors. The effect to speed is near to zero. It may actually slow down your code. However, you can't really see any difference be it ticked or not.
After the beginner phase: General optimizations
Advancing to the next level and getting to the general optimization stuff that isn't only VB related. The same things can apply to other languages as well.
About the IDE
One of the important things to note about is that when you are testing the speed of your code, you better compare the compiled code. P-Code is very different to compiled code and thus doing speed testing in the IDE is not worth of anything. P-Code code is faster when there is less commands to process, but compiled code can be much faster even when the amount of code increases. Basic math is also much faster when it is compiled, thus a complex mathematical algorithm can be really slow in the IDE, but very fast when compiled.
What to optimize?
You don't need to optimize everything. You don't need to optimize showing of a message box; you rarely need to optimize anything that relates to showing information to the user. What you should optimize is the heavy stuff that works in the background and stuff that are used often. For example, if you draw a custom mouse pointer in the game, you better do it as fast as possible, because it can dramatically effect to the Frames Per Second you can get: you have to draw the mouse pointer to each frame, so if it is slow to draw the mouse pointer, it does affect the overall speed of the end result.
For heavy stuff example, a processing of a 100 MB file should be optimized. What to consider? First of all, the amount of available RAM is important. Most computers have 256 to 1 GB of memory. You should always note the lower end and optimize so that your code works faster on the lower end computer. Thus you shouldn't read the complete file at once, but a small piece at a time and then process that.
Is API a solution?
Yes and no. If API allows you to handle a lot of data at once or makes it possible to do it using regular code, then the answer is yes. If it makes something that is complex to do using regular code, the answer is yes (for example, converting character codepage to another).
The answer is no if you have to call the API a lot. The classic example could be SetPixel: setting a single pixel using an API call, which has an overhead by calling a lot of stuff to set a single pixel, is nothing but slow. This function is only faster than PSet only because PSet has VB runtime overhead included in it: it actually calls the very same SetPixel.
API isn't a complete magical wand that does everything for you and fast. You should use API sparingly and only when there is no other way or it isn't worth reinventing a wheel. Calling API often is slow due to some overhead required for the call, so you shouldn't use it for small stuff.
Interesting fact about CopyMemory aka RtlMoveMemory: it is faster when compared to array handling when you are copying data forward. However, if you are copying data "backwards" in memory, moving it using VB code is slightly faster. Anyone is welcome to prove me wrong, this was the last result after thinking and testing it over a few weeks ago.
Comments and feedback
Send me a private message, this is a FAQ section so you would only get your message deleted. I didn't cover everything here as I wrote this all only off my head without peeking any other sources, so I'll probably write more stuff when I get into it again.
- additional information about one dimensional arrays and Option Base
- the order of your code (in a reply)
- the math (in a reply)