Skip to main content
NetworkAdminKB Logo

NetworkAdminKB.com

Go Search
NetworkAdminKB.com
Knowledge Base
VBScript Library
Utilities
  
NetworkAdminKB.com > Articles > Common and Uncommon Performance Optimizations for VBScript  

Web Part Page Title Bar image
Common and Uncommon Performance Optimizations for VBScript

 Common and Uncommon Performance Optimizations for VBScript

Author: NetworkAdminKb.com

Created: 2007-08-15

Modified: 2008-12-05

 

In this article I will be covering some basic and advanced performance optimizations for VBScript, as well as discussing some common misconceptions developers may have about VBScript performance.

 

Common VBScript Performance Penalties

1)      Creating and using Objects in VBScript is very slow.  Look for ways to do the same thing without using an object.

a.       For example the Dictionary Object may not be needed and an array or a custom written Class may work with greater speed.

b.      If you must create the object do so only once at a global level and pass the object into any procedure using ByRef.

2)      Loops are the enemy of performance

a.       Exit loops early when appropriate.  This is commonly called a “short circuit.”

                                                               i.      To exit a For Next Loop use “Exit For”.

                                                             ii.      To exit a Do LOOP use “Exit Do”

                                                            iii.      To exit a While Loop use “WEnd”

b.      Do multiple items in one loop, instead of performing separate loops.

                                                               i.      The trade off here may be ease of design or implementation

c.       Avoid loops if possible.

3)      Arrays

a.       Pass an array to a procedure using ByRef and not ByVal.  ByVal will copy the array in memory which will slow performance.

b.      Short circuit all array searches when the item is found.

4)      Sorting

a.       Quicksort has the best overall performance in VBScript.  Find a good quick sort routine and use it any time sorting is needed.

5)      Avoid using the following functions because they are very slow in VBScript

a.       Eval

b.      StrComp

c.       CreateObject

d.      GetObject

 

Uncommon VBScript Performance Optimizations

LBound and UBound

If you are using LBound or UBound once in a procedure then you can use it directly where your code requires it.  However, if LBound or UBound are used more than once then you should set a variable to these values upon entering the procedure and then use the variables in place of LBound and UBound.

 

Below is sample code to demonstrate the performance loss from calling UBound and LBound multiple times in a project.

 

Option Explicit

 

Dim x, z, intStart, intStop, intTemp, intTemp1

Dim aryAny1, strAny1

 

strAny1 = "a,b,c,d,e,f,g,h,i,j,k,l"

 

aryAny1 = Split(strAny1,",")

 

z = 10000000

 

intStart = Timer

For x = 1 to z

  intTemp = UBound(aryAny1)

  intTemp = Empty

Next 'x

intStop = Timer

Wscript.Echo intStop - intStart

 

intStart = Timer

intTemp1 = UBound(aryAny1)

For x = 1 to z

  intTemp = intTemp1

  intTemp = Empty

Next 'x

intStop = Timer

Wscript.Echo intStop - intStart

 

Comparison Operators

You would think that all 5 common comparison operators (>, <, <>, >=, <=) would have the same performance.  This is not true.  Greater than (>) and Greater than or equal to (>=) have much better performance.  When you want the most performance flip your comparison values around so they always perform the Greater than (>) and Greater than or equal to (>=) comparison.

 

Below is code demonstrating the performance of all 5 common comparison operators.  From this code you can determine the performance gain from using Greater than (>) and Greater than or equal to (>=) operators.

 

Option Explicit

 

Dim x, z, intStart, intStop

Dim intCount1, intCount2, intCount3, intCount4, intCount5

 

z = 10000000

 

intStart = Timer

For x = 1 to z

  If x < z Then intCount1 = intCount1 + 1

Next 'x

intStop = Timer

Wscript.Echo "<: " & intStop - intStart

 

intStart = Timer

For x = 1 to z

  If x > z Then intCount2 = intCount2 + 1

Next 'x

intStop = Timer

Wscript.Echo ">: " & intStop - intStart

 

intStart = Timer

For x = 1 to z

  If x <> z Then intCount3 = intCount3 + 1

Next 'x

intStop = Timer

Wscript.Echo "<>: " & intStop - intStart

 

intStart = Timer

For x = 1 to z

  If x >= z Then intCount4 = intCount4 + 1

Next 'x

intStop = Timer

Wscript.Echo ">=: " & intStop - intStart

 

intStart = Timer

For x = 1 to z

  If x =< z Then intCount5 = intCount5 + 1

Next 'x

intStop = Timer

Wscript.Echo "=<: " & intStop - intStart

 

Concatenating Strings

Concatenating strings using “&” or “+” is very slow.  If your program uses a lot of concatenations then you should place values into an array and use JOIN to build the string when you need to display or work with it.

 

Below is code demonstrating the performance gain from using an array to store the various parts of the string, then using JOIN to work with or display the string.

 

Option Explicit

 

Dim x, z, intStart, intStop

Dim strTemp

 

z = 100000

 

intStart = Timer

For x = 0 to z

  strTemp = "a" & strTemp

Next 'x

intStop = Timer

Wscript.Echo intStop - intStart

Wscript.Echo Len(strTemp)

strTemp = Empty

 

intStart = Timer

For x = 0 to z

  strTemp = strTemp & "a"

Next 'x

intStop = Timer

Wscript.Echo intStop - intStart

Wscript.Echo Len(strTemp)

 

intStart = Timer

For x = 0 to z

  ReDim Preserve aryTemp(x)

  aryTemp(x)="a"

Next 'x

strTemp = Join(aryTemp,"")

intStop = Timer

Wscript.Echo intStop - intStart

Wscript.Echo Len(strTemp)

 

Note: in this example “a” is concatenated over and over again, but in real life this would be a part of a sentence or a word.

 

The results from this test are interesting because concatenating to the end of the string is faster than adding to the beginning, which would also be true using the array method.

 

While the performance gain using this method is significant the trade off for ease of use may not be worth it.  In programs requiring large amount of string concatenation this may be of benefit.  I would also recommend creating a CLASS to handle the conversion to and from the array to make it more useful in your program.

 

By increasing the value of z, you can also demonstrate that the amount of time it takes to concatenate strings is affected by the length of the string, and that this is not a linear progression (i.e.: 2 times z results in greater than double the time).

 

Specifying a data type for Numbers

By default all numbers (and strings) are considered a Variant data type.  It is possible to force numbers to by a particular data type.  The possible data types for numbers are: Byte (CByte), Integer (CInt), Currency (CCur), Long (CLng), Single Precision (CSng), Double Precision (CDbl). 

 

In general for the best performance you should not specify a particular data type for a number.  If you must force a data type, avoid Currency and Double Precision as they perform slightly slower than the numerical other data types.

 

Below is code demonstrating the performance loss from using the Currency and Double Precision data types.

 

Option Explicit

 

Dim x, z, intStart, intStop, w, y

Dim intCount1

 

z = 12000000

 

intStart = Timer

For x = -z to z

  intCount1 = x

Next 'x

intStop = Timer

Wscript.Echo "default: " & intStop - intStart

 

'To test Integers and Byte I must be creative using two loops,

'The X loop makes sure the number of attempts matches the other tests

'The W loop actually tests the appropriate data type.

y = 250

w = CByte(w)

y = CByte(y)

intCount1 = 0

intCount1 = CByte(intCount1)

intStart = Timer

For x = -(z/(y*2)) to (z/(y*2))

  For w = -y to y

    intCount1 = w

  Next 'w

Next 'x

intStop = Timer

Wscript.Echo "CByte: " & intStop - intStart

 

y = 5000

w = CInt(w)

y = CInt(y)

intCount1 = 0

intCount1 = CInt(intCount1)

intStart = Timer

For x = -(z/(y*2)) to (z/(y*2))

  For w = -y to y

    intCount1 = w

  Next 'w

Next 'x

intStop = Timer

Wscript.Echo "CInt: " & intStop - intStart

 

x = CCur(x)

z = CCur(z)

intCount1 = CCur(intCount1)

intStart = Timer

For x = -z to z

  intCount1 = x

Next 'x

intStop = Timer

Wscript.Echo "CCur: " & intStop - intStart

 

x = CLng(x)

z = CLng(z)

intCount1 = CLng(intCount1)

intStart = Timer

For x = -z to z

  intCount1 = x

Next 'x

intStop = Timer

Wscript.Echo "CLng: " & intStop - intStart

 

x = CSng(x)

z = CSng(z)

intCount1 = CSng(intCount1)

intStart = Timer

For x = -z to z

  intCount1 = x

Next 'x

intStop = Timer

Wscript.Echo "CSng: " & intStop - intStart

 

x = CDbl(x)

z = CDbl(z)

intCount1 = CDbl(intCount1)

intStart = Timer

For x = -z to z

  intCount1 = x

Next 'x

intStop = Timer

Wscript.Echo "CDbl: " & intStop - intStart

 

Specifying CBool as the data type

In VBScript you can use Boolean logic to create a Boolean data type.  However, some programmers will include the CBool conversion function in addition to the logic thinking that it is required to receive a Boolean variable type.  This is not true and also slows the performance of the statement by about 40-50%.

 

Below are is code demonstrating the performance of using Boolean logic with and without the CBool data type.

 

Option Explicit

 

Dim x, z, intStart, intStop

Dim blnTemp

 

z = 5000000

 

intStart = Timer

For x = 1 to z

  blnTemp = CBool(x <> z)

Next 'x

intStop = Timer

Wscript.Echo "blnTemp: " & blnTemp

Wscript.Echo intStop - intStart

 

blnTemp = Empty

intStart = Timer

For x = 1 to z

  blnTemp = (x <> z)

Next 'x

intStop = Timer

Wscript.Echo "blnTemp: " & blnTemp

Wscript.Echo intStop - intStart

 

Incremental ReDim of Array

There is moderate performance loss by incrementally adding one value to an array over and over again.  The performance loss is about 10-15 seconds for the first 500,000 elements.  The time it takes to add an additional 100,000 elements one at a time then continually increases.  The length of the item or the data type (string vs. number) of the item has little effect on the time it takes to add an additional element to the array.

 

Below is code demonstrating the performance comparison of adding elements to an array in 100,000 increments.  The first For w loop adds elements one at a time, while the second For w loop adds 100,000 elements at a time.

 

Option Explicit

 

Dim x, z, intStart, intStop

Dim w, y

 

z = 100000

y = 0

For w = 1 to 5

  intStart = Timer

  For x = y to z*w

    ReDim Preserve aryTemp(x)

    'aryTemp(x)="abcdefghijklmnopqrstuvwxyz"

    aryTemp(x)= w * x

  Next 'x

  intStop = Timer

  Wscript.Echo intStop - intStart

  Wscript.Echo "UBound: " & UBound(aryTemp)

  y = y + z

Next 'w

 

Wscript.Echo

y = 0

For w = 1 to 5

  intStart = Timer

  For x = y to z*w

    ReDim Preserve aryTemp1(z*w)

    'aryTemp(x)="abcdefghijklmnopqrstuvwxyz"

    aryTemp1(x)= w * x

  Next 'x

  intStop = Timer

  Wscript.Echo intStop - intStart

  Wscript.Echo "UBound: " & UBound(aryTemp1)

  y = y + z

Next 'w

 

The trade off here is really about ease of programming, a 15 second loss for 500,000 elements may be worth it if it makes programming your project easier.  However, if you want to squeeze out the most performance declare a fixed array at the beginning of your project or allocate space in chucks as shown in the code above.

 

Some Misconceptions about VBScript Performance

IF Statements

Some developers may believe that because VBScript is a scripting language and not a compiled language less lines means more speed.  This is not always the case with VBScript.  There is no significant difference between one line IF statements and multiple line IF…END IF statements.

Below is sample code to demonstrate the lack of performance different between one line IF and multiple line IF…END IF statements.  In testing this code on average there was a 0.2 seconds difference between the IF statements during 50million comparisons.

 

Option Explicit

 

Dim x, z, intStart, intStop

 

z = 50000000

 

intStart = Timer

For x = 1 to z

  If x = z Then Wscript.Echo "1 match"

Next 'x

intStop = Timer

Wscript.Echo intStop - intStart

 

intStart = Timer

For x = 1 to z

  If x = z Then

    Wscript.Echo "2 match"

  End If

Next 'x

intStop = Timer

Wscript.Echo intStop - intStart

 

Comment Statements

Another common misconception about VBScript performance is that too many comments in a script can slow performance.  This is simply not true.  The reason for this is due to the fact that the script is read once then stored in memory.  When storing the script in memory the comments are not stored.  Any performance loss from comments is encountered during the initial read of the script into memory.

 

Here is example code demonstrating that the number of comments has no effect on performance.

 

Option Explicit

 

Dim x, z, intStart, intStop

 

z = 100000000

 

intStart = Timer

For x = 1 to z

  'Comment 1

Next 'x

intStop = Timer

Wscript.Echo intStop - intStart

 

intStart = Timer

For x = 1 to z

  'Comment 1

  'Comment 2

  'Comment 3

  'Comment 4

  'Comment 5

  'Comment 6

  'Comment 7

  'Comment 8

  'Comment 9

  'Comment 10

Next 'x

intStop = Timer

Wscript.Echo intStop - intStart

 

Summary

For the most part performance optimization in VBScript is kind of an oxymoron.  Using a scripting language for projects that require high performance is not really a good practice.  For the most part a real programming language that can create an executable would provide much better performance.  However, if you need added performance from your VBScript program following any of the suggestions above will help you squeeze that performance out.

 
 NetworkAdminKB.com
 Copyright © 2008 NetworkAdminKB.com, All rights reserved. Terms of Use | Contact US