Tuesday, March 9, 2010

Code Optimisation Techeniques

VBScript – Code optimization Techniques


1. Use select case instead of If else if

2. StrComp vs 'String1=String2' [5/2/2001]


StrComp() is 100+% faster than using Ucase, for capital unsensitive strings. I actually never knew that strComp() existed. But I think I'm going to try to implent it now where possible. This test was based on the standard method: 500.000 iterations, 5 times.

Used Code:
Public Sub TestOne()
Dim strTest1 As String, strTest2 As String
strTest1 = UCase$("all j00r b453 r b3l0nG 70 U5")
strTest2 = UCase$("ALL J00r base R Bel0NG 70 U5")
If strTest1 = strTest2 Then
End If
End Sub

Public Sub TestTwo()>BR? Dim strTest1 As String, strTest2 As String
strTest1 = "all j00r b453 r b3l0nG 70 U5"
strTest2 = "ALL J00r base R Bel0NG 70 U5"
If StrComp(strTest1$, strTest2$, vbTextCompare) = 0 Then
End If
End Sub

3.
So much effect for so little change of code. These are only the statistics of the "Left" function, but I've also done some tests using "Ucase", "Lcase" and "Trim". All these functions are much faster using the "$" sign after the function. This happens for a simple reason: The functions return a variant without the $ sign. And variants are very slow, you should never use them.
Code Used:
Public Sub TestOne()
Dim strReturn As String
strReturn = Left("This is a test", 4)
End Sub
Public Sub TestTwo()
Dim strReturn As String
strReturn = Left$("This is a test", 4)
End Sub
4

Math

Use "X \ 1" instead of "Cint(x)" [5/2/2001]
"X \ 1" is a lot faster, and the end result is the same. The speed increase is actually more than I would have expected. But as with many other optimizations, this test has been done with 500.000 iterations. So for small loops you might not notice it.
Code used:
Public Sub TestOne()
Dim lngReturn As Long
lngReturn = CInt(100.543253)
End Sub
Public Sub TestTwo()
Dim lngReturn As Long
lngReturn = 100.543253 \ 1
End Sub


5

Always use "\" instead of "/" [5/1/2001]
Major performance gain here! For integer calculations you should always use "\" instead of "/" Using "\" is faster because f you divide by "/" the values will first be converted to singles. So for Sin/Cos/Tan operation you should still use "/" if you want to have precision. code used:
Public Sub TestOne()
Dim intResult As Integer
intResult = 100 / 50
End Sub
Public Sub TestTwo()
Dim intResult As Integer
intResult = 100 \ 50
End Sub
6

Use "x * x" instead of "x ^ 2" [4/30/2001]
You can use "x * x" instead of "x ^ 2". The end result will be the same. Well, I think the statistics prove themself, it's definetly worth to change your code to the optimized method! But As you can see the time for the calculations is very low anyways. Not even a second for 500.000 iterations Maybe with very large iterations you might notice it. Still I recommend to change the code since we want to have our programs running at the maximal speed possible, don't we? I'm not sure but maybe for larger quadratic calculations the routine might become faster. For example "x ^ 5" can also be done using "x * x * x * x * x"
Public Sub TestOne()
Dim dblResult As Double
dblResult = 4 ^ 2
End Sub
Public Sub TestTwo()
Dim dblResult As Double
dblResult = 4 * 4
End Sub
7
Arrays: Temporary variables [5/2/2001]
Well no doubt about it. Temporary variables are going to speed up your program. I have to say that I had to wait longer than expect to complete this routine. Anyway, if you're often pointing to an array, you've definetly got to use temporary values. Check the source code for an example. Note that I've done the test 5 times, but there was only 1 main iteration, cause the For...Next loops where long enough. Also note that in the first test without the temporary variable, I didn't declare the "lngTemp" variable. We didn't use it there, so no extra variable declaration.
Used code: Public Sub TestOne()
Dim I As Long, J As Long
Dim myArray(1 To 50000) As Long
For I = 1 To 50000
For J = I + 1 To 50000
If myArray(I) = myArray(J) Then
End If
Next
Next
Erase myArray
End Sub
Public Sub TestTwo()
Dim I As Long, J As Long
Dim myArray(1 To 50000) As Long
Dim lngTmp As Long
For I = 1 To 50000
lngTmp = myArray(I)
For J = I + 1 To 50000
If lngTmp = myArray(J) Then
End If
Next
Next
Erase myArray
End Sub
8
For…Each vs. For...Next [5/2/2001]
Using For...Next in arrays is a lot faster than For...Each. I'm not sure why this is caused, but probably also because you've got to use a variant as loop index for the "For...Each". And any serious programmer doesn't use a variant in his/her applications. I've used Lbound() and Ubound() in the For...Next loop, cause we do not have to worry about those two values, like in For...Each. No 500.000 iterations this time. I've done 1 iteration, the array was large enough to be precise enough. The test has been done 5 times though.
Used Code:
Public Sub TestOne()
Dim MyArray(1 To 100000)
Dim I As Variant
For Each I In MyArray
Next
End Sub
Public Sub TestTwo()
Dim MyArray(1 To 100000)
Dim I As Long
For I = LBound(MyArray) To UBound(MyArray)
Next
End Sub
9
For…Next: Always use longs [5/2/2001]
Never use anything else than longs in loops. Longs are the fastest variable type in Visual Basic. It's easy to explain why: They are 32bit, your processor is 32 bit, and every other type that isn't 32 bit needs to be converted to 32 bit (which takes time). Okay, now I could have used integers for this test. Integers are slower than longs, but just running an test between a long and integer, without anything between For...Next, will not really matter. But in larger loops, you'll always see that the Long variable type will win in performance.
So that's why I decided to use a single. And you can see the difference between it, definetly. I might add that I haven't used the normal test system for this test: 1 iteration, done 5 times. But the long and single test both contained 100000 iterations, so it should be all right.
Code used:
Public Sub TestOne()
Dim I As Single
For I = 0 To 100000
Next I
End Sub
Public Sub TestTwo()
Dim I As Long
For I = 0 To 100000
Next I
End Sub
11
'With' vs.' No With' [5/2/2001]
The results of this test are very irregular. Sometimes "With" wins and some "No with" wins. I've done this test 10 times, but everytime the same results... I'm not sure why this happens. I always thought that "With" would be (much) faster anyway. It could be the form I've used for this test, but it's highly unlikely. For this test I've done 5000 iterations, and done the test 5 times. Changing properties take so much time in VB. I have limitted the form calls to properties that are not graphical depending on something.
Used code:
Public Sub TestOne()
frmTest.Caption = "test"
frmTest.Enabled = True
frmTest.CurrentX = 10
frmTest.ScaleMode = vbPixels
frmTest.Tag = "test"
frmTest.Tag = "test1"
frmTest.Tag = "test2"
frmTest.Tag = "test3"
frmTest.Tag = "test4"
End Sub
Public Sub TestTwo()
With frmTest
.Caption = "test"
.Enabled = True
.CurrentX = 10
.ScaleMode = vbPixels
.Tag = "test"
.Tag = "test1"
.Tag = "test2"
.Tag = "test3"
.Tag = "test4"
End With
End Sub
12
Memory

Static vs. Public variables [5/3/2001]
Sometimes I use Static variables, but I think I'm going for public now. Not that it really matters that much, but any performance increase is welcome for me. I've used the standard method for this test: 500.000 iterations, 5 times.
Used Code:
Declaration section: Private Var1 As Long
Public Sub TestOne()
Static Var2 As Long
Var2 = Var2 + 1
End Sub
Public Sub TestTwo()
Var1 = Var1 + 1
End Sub
13
Methods

Use Byref or Byval? [5/2/2001]
ByRef arguments are 1/3 faster than Byval. If you do not explcitly declare arguments as Byval or Byref, VB will use ByRef as default. So if you never specify ByVal, there won't be any speed gain for you here. Except that you can specify ByRef explicit (see other VB Fibre article)
Code used:
Public Sub TestOne(ByVal lngValue1 As Long, ByVal strString1 As String, ByVal bByte1 As Byte)
'empty
End Sub
Public Sub TestTwo(ByRef ngValue1 As Long, ByRef strString1 As String, ByRef bByte1 As Byte)
'empty
End Sub
14
Specify ByRef explictly [5/2/2001]
A very little speed increase. I expected a larger increase... Anyway, it's always better to declare arguments byval or byref explicitly. You can then see how values are passed, and see if it returns anything directly. I'm not sure if it's worthy to change all your subs and functions to Byref, because the speed increase ain't that much.
Code used:
Public Sub TestOne(lngValue1 As Long, strString1 As String, bByte1 As Byte)
'empty
End Sub
Public Sub TestTwo(ByRef ngValue1 As Long, ByRef strString1 As String, ByRef bByte1 As Byte)
'empty
End Sub
15
To call or not to call? [5/1/2001]
The difference between call or no call is very small. The funny thing is that there's a difference if you call a sub or a function. That's why I'm probably going to add another test to check if "no call" is faster for subs. The results of this test are based on a function, the function returns a string.
Public Function TestOne() As String
TestOne = "empty"
End Function
This was function was called 500.000 times using "Call Testone" and "Testone", and done 5 times

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.