How to Performance Test VBScript code for Performance Optimization

Author: NetworkAdminKB.com

Created: 2008-10-22

Modified: 2009-01-03

 

So you want to optimize your VBScript code to increase performance.  I have written this article to explain the basic process and perform a demonstration.   This will hopefully help you devise a way to performance test and performance optimize your code.

 

First, let’s define the various parts of Performance Testing and Performance Optimization.

 

Performance Testing is the process of running program code under a specific set of conditions and recording the result (the amount of time it takes to run).  This is usually done with a static or random dataset.  A static dataset may provide more predictable results during the test, while a random data may produce slightly varied results over a wider range of values.

 

Optimization is the process of identifying potential bottlenecks in the code and creating new code that will alleviate the bottleneck.

 

Performance Optimization is the process of Performance Testing current code, Optimizing the code, then Performance Testing the new optimized code.  This can be done in a repeatable fashion until the desire performance is maximized.

 

Step 1 Performance Testing

It is highly recommended that you performance test specific pieces of code at a time, and not an entire program.  The easiest pieces of code to performance test are individual procedures.  Use the following process to create your first Performance Test.

 

1)      Create a New VBScript file (codetester.vbs)

2)      At the top of the codetester.vbs file type the following line.  This will help identify programming issues when isolating a procedure from a whole program.

a.       Option Explicit

3)      Select a suitable procedure from your code to test and place codetester.vbs file.

4)      Place the following code at the bottom of the codetester.vbs file.

 

Dim x, z, intStart, intStop

z = 100000

intStart = Timer

For x = 1 to z

  'Call your procedure here

Next 'x

intStop = Timer

Wscript.Echo intStop - intStart

 

5)      Add a call to your procedure inside the For Next Loop as indicated

6)      Add any support Constants, variables, etc that may be needed for your Procedure to run in this isolated fashion.  Good programming techniques greatly aid in being able to performance test sections of code.

7)      Run the code one time.

8)      View the timed results.  If the results take less than 5 seconds to process, then increase the value of Z until the test runs for at least 5 seconds.  If the test runs for longer than 1 minute you may want to reduce the value of Z so that the test runs in under a minute, but keep the value of Z to a minimum of about 1000.

a.       This is done so that a meaningful comparison can be done against optimized code later.  The time difference between optimized and un-optimized code will become greater the long it is run.  This simplifies the comparison for the “optimized” code.

9)      Run the code between 3-30 times and compute an average for the number of runs.

a.       Statistically you need 30 runs so that any deviation can be standardized when using random datasets, but usually 3-5 runs is sufficient for our purposes.

 

Step 2 Optimize the Code

This can be tricky and overwhelming if you are unfamiliar with the internal workings VBScript.  You will probably need to learn about specific properties of VBScript to help you determine what are and are not good performance optimizations.

 

After you learn the general performance pitfalls of VBScript you will need to focus on your algorithms.  In general you should have an idea about how to improve the existing algorithm then test it to see if it works.  The key here isn’t so much that you get it right, because even if you get it wrong you will learn what NOT to do in the future.

 

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

 

Step 3 Performance Optimization

After you have developed the new function you will need to test it for performance and compare it against the original function.  To do this, follow the same general procedure outlined in Step 1 above.

 

Compare the results and determine which algorithm provides the best results.

 

Example Code for Performance Optimization

Option Explicit

 

'********************************************************************

'*

'* Function blnStrComp

'*

'* Purpose: Returns a Boolean indicating if the strings provided are

'*            equal based on case sensitive or case insensitive

'*            comparison.  Numbers are converted to strings for

'*            comparison.

'*

'* Input:   strComp1  A string to compare with strComp2

'*          strComp2  A string to compare with strComp1

'*          blnCase   A Boolean indicating case sensitive comparisons.

'*                      True  = Case Sensitive comparison

'*                      False = Case Insensitive comparison (Default)

'*

'*  Notes: UCase and LCase convert numbers to strings for comparison

'*

'* Output:  Returns a Boolean indicating if the strings provided are

'*            equal based on case sensitive or case insensitive

'*            comparison.

'*            True  = The strings are equal

'*            False = The strings are not equal.

'*

'********************************************************************

Function blnStrComp(ByVal strComp1, ByVal strComp2, ByVal blnCase)

  'Version 1.0 2008-05-18

 

  Select Case StrComp(strComp1, strComp2, ReturnCaseComparisonValue(blnCase))

    Case 0

      blnStrComp = True

    Case Null, -1, 1

      blnStrComp = False

    Case Else

      'Return Default Value

      blnStrComp = False

  End Select 'StrComp(strComp1, strComp2, ReturnCaseComparisonValue(blnCase))

End Function 'blnStrComp

 

'********************************************************************

'*

'* Function ReturnCaseComparisonValue

'*

'* Purpose: Returns the proper VB String Comparison Constant based on

'*            the provided Boolean in blnCase

'*

'* Input:   blnCase   A Boolean indicating case sensitive comparisons.

'*                      True  = Case Sensitive comparison

'*                      False = Case Insensitive comparison (Default)

'*

'* Output:  Returns the proper VB String Comparison Constant based on

'*            the provided Boolean in blnCase.

'*            vbBinaryCompare 0 Perform a binary (case sensitive) comparison.

'*            vbTextCompare   1 Perform a textual (case insensitive) comparison.

'*          Returns vbTextCompare if blnCase is anything other than True

'*             (i.e. Empty, Null, a String, etc).

'*

'********************************************************************

Function ReturnCaseComparisonValue(ByVal blnCase)

  'Version 1.0 2008-05-18

 

  Select Case blnCase

    Case True

      'vbBinaryCompare provides case sensitive comparison

      ReturnCaseComparisonValue = vbBinaryCompare

    Case False

      'vbTextCompare provides case insensitive comparison

      ReturnCaseComparisonValue = vbTextCompare

    Case Else

      'Return Default Setting.

      ReturnCaseComparisonValue = vbTextCompare

  End Select 'blnCase

End Function 'ReturnCaseComparisonValue

 

 

'********************************************************************

'*

'* Function blnStrCompV2

'*

'* Purpose: Returns a Boolean indicating if the strings provided are

'*            equal based on case sensitive or case insensitive

'*            comparison.  Numbers are converted to strings for

'*            comparison.

'*

'* Input:   strComp1  A string to compare with strComp2

'*          strComp2  A string to compare with strComp1

'*          blnCase   A Boolean indicating case sensitive comparisons.

'*                      True  = Case Sensitive comparison

'*                      False = Case Insensitive comparison (Default)

'*

'* Output:  Returns a Boolean indicating if the strings provided are

'*            equal based on case sensitive or case insensitive

'*            comparison.

'*            True  = The strings are equal

'*            False = The strings are not equal.

'*

'*  Notes: UCase and LCase convert numbers to strings for comparison

'*

'* Changes:

'* 2008-05-29: Complete re-write not using StrComp function to

'*               improve speed.

'********************************************************************

Function blnStrCompV2(ByVal strComp1, ByVal strComp2, ByVal blnCase)

  'Version 2.0 2008-05-29

 

  Select Case blnCase

    Case True

      'case sensitive comparison

       blnStrCompV2 = CBool(strComp1 = strComp2)

    Case False

      'case insensitive comparison

      blnStrCompV2 = CBool(UCase(strComp1) = UCase(strComp2))

    Case Else

      'Default case insensitive comparison

      blnStrCompV2 = CBool(UCase(strComp1) = UCase(strComp2))

  End Select 'blnCase

End Function 'blnStrCompV2

 

Dim x, intStart, intStop, y, z

 

z = 300000

intStart = Timer

For x = 1 to z

  blnStrComp "hello", "Hello", True

  blnStrComp "Hello", "Hello", True

  blnStrComp "hello", "Hello", False

  blnStrComp "hello", "Hello", Empty

  blnStrComp vbNull, "Hello", Null

  blnStrComp Empty, Empty, "hello"

Next 'x

intStop = Timer

Wscript.echo intStop - intStart

 

intStart = Timer

For x = 1 to z

  blnStrCompV2 "hello", "Hello", True

  blnStrCompV2 "Hello", "Hello", True

  blnStrCompV2 "hello", "Hello", False

  blnStrCompV2 "hello", "Hello", Empty

  blnStrCompV2 vbNull, "Hello", Null

  blnStrCompV2 Empty, Empty, "hello"

Next 'x

intStop = Timer

Wscript.echo intStop - intStart

Article ID: 19, Created On: 9/16/2011, Modified: 9/16/2011