-
1 Attachment(s)
Re: tips for optimizing vb code
That is not a fair test though for at least 3 reasons I can see.
This is a less biased benchmark...
VB Code:
Sub Main()
Dim t As Integer
Dim temp As String
Dim i, j, k As Integer
For k = 1 To 5
t = Environment.TickCount
j = 0
For i = 1 To 1000000000
WasteOfTime()
Next i
t = Environment.TickCount - t
temp = "Run " & k & ": For: " & t & "ms"
'#####
t = Environment.TickCount
j = 0
Do Until j = 1000000000
j += 1
WasteOfTime()
Loop
t = Environment.TickCount - t
temp &= ", Do: " & t & "ms"
Console.WriteLine(temp)
Next k
Console.ReadLine()
End Sub
Public Sub WasteOfTime()
Dim s As String = "A"c
s = Nothing
End Sub
NOTE: I haven't got any decent timer code on me at the moment so feel free to replace the Tickcount with something more accurate.
PS (The wasteoftime method is just to make sure the compiler doesn't discard pointless loops, it also gives the for loop something to do)
-
Re: tips for optimizing vb code
I think someone should look at the difference in machine code generated by the FOR loop vs the DO loop.
Let's say that the "slower" one simply has one or two op-codes of extra machine code. That is "execution time" meaningful in this "loop that does nothing-but-loop" time test.
But would be completely trivial in a real loop that is doing something within the loop that actually takes some time!
-
Re: tips for optimizing vb code
Quote:
Originally Posted by szlamany
I think someone should look at the difference in machine code generated by the FOR loop vs the DO loop.
Let's say that the "slower" one simply has one or two op-codes of extra machine code. That is "execution time" meaningful in this "loop that does nothing-but-loop" time test.
But would be completely trivial in a real loop that is doing something within the loop that actually takes some time!
Tell ya what, I will tomorrow maybe =)
btw - I think this effort is a waste of time. A for may provide a better solution then do on certain problems and vice versa.
-
Re: tips for optimizing vb code
-
Re: tips for optimizing vb code
Quote:
Originally Posted by dee-u
Quote:
Even using small names for variables could make it
gain something in speed (you know, like "Dim a as
string" and "Dim b as long"), but then you will chatch
an headache when have to try to maintain code or develope
more after some times...
That is untrue. The name you use is just a label applied to a memory location while you're coding it, it doesnt actually appear in the compiled exe.
-
Re: tips for optimizing vb code
Quote:
Originally Posted by Merri
Here you have some VB6 code that shows For ... Next is slower than Do ... Loop. Both do as equal amount of work within the loop as possible:
VB Code:
'For ... Next
For A = 1 To Iterations
A = A
Next A
'Do ... Loop
A = 1
Do While A < Iterations
A = A + 1
Loop
Doing 1 000 000 000 iterations results ~1550 ms vs. ~1030 ms on my machine.
And the full source...
However I have found just the opposite for similar code:
VB Code:
iter = 100000000
'First method
For i = 1 To iter
j = i
Next
'Second method
i = 1
Do While i <= iter
j = i
i = i + 1
Loop
The first method takes 13.8 seconds while the second 34.9
-
Re: tips for optimizing vb code
Quote:
Originally Posted by krtxmrtz
However I have found just the opposite for similar code:
VB Code:
iter = 100000000
'First method
For i = 1 To iter
j = i
Next
'Second method
i = 1
Do While i <= iter
j = i
i = i + 1
Loop
The first method takes 13.8 seconds while the second 34.9
Maven made sure to have something very similar in the loop - so the test would be just the loop construct.
You are doing two things in the second loop, and one thing in the first loop - having the guts of the loop be different makes the test of the "loop construct" less valid.
-
Re: tips for optimizing vb code
Quote:
Originally Posted by szlamany
Maven made sure to have something very similar in the loop - so the test would be just the loop construct.
You are doing two things in the second loop, and one thing in the first loop - having the guts of the loop be different makes the test of the "loop construct" less valid.
That's precisely the point. How would you construct the second loop so that it did the same job as the first loop?
-
Re: tips for optimizing vb code
I actually think that the contents of the loop should be something that has nothing to do with A=A or I=J - something that's got more meat to it.
-
Re: tips for optimizing vb code
Quote:
Originally Posted by szlamany
I actually think that the contents of the loop should be something that has nothing to do with A=A or I=J - something that's got more meat to it.
You bet. This is it:
VB Code:
'Loop #1
'*************************************************
For i = 0 To uLim
For n = 1 To 3
k = k + 1
Vector(k) = Gray(i)
If (k - GpL) Mod dummy = 0 Then
For m = 1 To nb2a
k = k + 1
Vector(k) = 0
Next
End If
Next
Next
'Loop #2
'*************************************************
i = 0
Do
n = 1
Do
k = k + 1
Vector(k) = Gray(i)
If (k - GpL) Mod dummy = 0 Then
m = 0
Do While m < nb2a
k = k + 1
Vector(k) = 0
m = m + 1
Loop
End If
n = n + 1
Loop While n <= 3
i = i + 1
Loop While i <= uLim
I tested it for these values:
uLim = 58805
nb2a = 2
GpL = 726
dummy = 728
For loop #1 the time was 0.328 s. whereas loop #2 took 0.437 s.
-
Re: tips for optimizing vb code
Quote:
Originally Posted by krtxmrtz
You bet. This is it:
VB Code:
'Loop #1
'*************************************************
For i = 0 To uLim
For n = 1 To 3
k = k + 1
Vector(k) = Gray(i)
If (k - GpL) Mod dummy = 0 Then
For m = 1 To nb2a
k = k + 1
Vector(k) = 0
Next
End If
Next
Next
'Loop #2
'*************************************************
i = 0
Do
n = 1
Do
k = k + 1
Vector(k) = Gray(i)
If (k - GpL) Mod dummy = 0 Then
m = 0
Do While m < nb2a
k = k + 1
Vector(k) = 0
m = m + 1
Loop
End If
n = n + 1
Loop While n <= 3
i = i + 1
Loop While i <= uLim
I tested it for these values:
uLim = 58805
nb2a = 2
GpL = 726
dummy = 728
For loop #1 the time was 0.328 s. whereas loop #2 took 0.437 s.
It's pretty much a complete waste of time to compare loops. As I said above, one type of loop may work good with one algorithm and the other bad. That is why there is more then 1 type of loop. One can provide a better solution in an algorithm then the other.
If you want to research something a bit more useful when analyzing loops, then you may want to read up on Big-O notation. Learn the difference between a O(N) loop and a O(N^2) loop. You'll walk away a better programmer. Just do a search on it at you're fav search engine.
-
Re: tips for optimizing vb code
Quote:
Originally Posted by Maven
If you want to research something a bit more useful when analyzing loops, then you may want to read up on Big-O notation. Learn the difference between a O(N) loop and a O(N^2) loop. You'll walk away a better programmer. Just do a search on it at you're fav search engine.
That's pretty much straightforward, but without knowing the guts of the various loop instructions i.e. how they map to machine code, it's not that easy to know beforehand what the best loop for a particular problem may be, that's why I set to copmpare loops.
-
Re: tips for optimizing vb code
Another tip for your loops
<= is slower than =
so you might retest the speed of the Do loop again using this
VB Code:
'add an extra point to iter
iter = 100000001
Do Until i = iter
j = i
i = i + 1
Loop
-
Re: tips for optimizing vb code
On a completely unrelated note, when facing extreme situations, it makes sense to always use subs rather than functions, and "returning" the value of the function into a variable passed ByRef.
VB Code:
Private Function sf(ByRef v As Boolean)
sf = True
End Function
'________________________________________
Private Sub sf2(ByRef v As Boolean, ByRef dd As Boolean)
dd = True
End Sub
'sf performs at ~55% of sf2's speed.
-
Re: tips for optimizing vb code
Another tip that must be added, Maven.
Single line If statements
is faster than Block If's
VB Code:
If X >= 100 Then
X = 0
End If
-
Re: tips for optimizing vb code
And IIf is the slowest BTW.
-
Re: tips for optimizing vb code
Yup. Also, weren't ElseIf statments faster than Select Case? We proved that in this one thread.
-
Re: tips for optimizing vb code
i think that was my thread^^
-
Re: tips for optimizing vb code
Quote:
Originally Posted by Jacob Roman
Yup. Also, weren't ElseIf statments faster than Select Case? We proved that in this one thread.
Case:
VB Code:
Select Case a
Case 10: MyFunc
Case 14: YourFunc
Case 15: Beep 'For arguments sake.
End Select
If:
VB Code:
If (a = 10) Then
MyFunc
ElseIf (a = 14) Then
YourFunc
ElseIf (a = 15) Then
Beep
End If
Keep in mind that an if block really looks like this:
VB Code:
If (a = 10) Then
MyFunc
Goto AfterIfs
End If
If (a = 14) Then
YourFunc
Goto AfterIfs
End If
If (a = 15) Then
Beep
End If
AfterIfs:
A case statement in ASM looks like this (if it were compiled badly, for arguments sake):
Code:
cmp a, 10 ;compare a with 10
jne case2 ;jump if not equal case2
call MyFunc ;call MyFunc
jmp exitcase ;exit case
case2:
cmp a, 14
jne case3
call YourFunc
jmp exitcase
case3:
cmp a, 15
jne exitcase
call Beep
exitcase:
Which looks remarkably like the rewritten if block. I would reckon a good compiler would recognise this and choose only the most efficient ladder, but this is an MS product we are talking about here. Either way, every value is compared (or at least until a match). A good speedup would be to put the most frequent or likely comparison first.
-
Re: tips for optimizing vb code
Quote:
Originally Posted by Maven
A division instruction is 50 clock cycles, which is crazy! lol.
On Pentium, but it is faster with newer processors.
For example, i remember that a division uses 18 clock cycles on AMD K6-2 processors.
In fact, a multiplication by 0.5 is slower, because it converts the long to a float (moving the data on the stack), then it does the multiplication, and convery the result to long.
And conversions from integer to float and float to integer are relatively slow.
I compared the two operations in C++, with MinGW and Borland C++ 5.5.
And the integer division is about 1.8 times faster with my K6-2 333Mhz processor for MinGW (In fact, with a constant division factor the integer division is optimized like a multiplication by the number inverse, and in that case an integer division by 3 is 5 times faster than the float division).
An integer division by 2 is even faster, because it uses an arithmetic shift.
Borland's compiler uses extremely slow code to convert floats to integers (i don't understand why, but that is the case), so it is 5 times slower with float than with integers.
Conclusion : use float multiplications when variables are floats, and integer division when variables are integers.
-
Re: tips for optimizing vb code
Quote:
Originally Posted by Maven
I normally go to asm when I have a very long switch because there is some cool tricks in asm you can do that you simply cannot do in any other langauge. I can compare a charecter with every charecter in the ascii set with 1 compare statement in asm where it would take around 255 in any other langauge.
A jump table is automatically generated by some C++ compilers when the switch statement is used with many cases (at least 4 for Borland C++).
I verified it for Borland C++ and gcc.
The standard says that the switch statement can only handle constants cases. And i am sure that the standard was thinking about jump tables.
Moreover for some special cases it is easy to manually manipulate table of pointers to function in C++ (but of course, it does not replace JUMP tables).
But, VB don't uses these optimizations.
-
Re: tips for optimizing vb code
Quote:
Originally Posted by SuperKoko
On Pentium, but it is faster with newer processors.
For example, i remember that a division uses 18 clock cycles on AMD K6-2 processors.
In fact, a multiplication by 0.5 is slower, because it converts the long to a float (moving the data on the stack), then it does the multiplication, and convery the result to long.
And conversions from integer to float and float to integer are relatively slow.
I compared the two operations in C++, with MinGW and Borland C++ 5.5.
And the integer division is about 1.8 times faster with my K6-2 333Mhz processor for MinGW (In fact, with a constant division factor the integer division is optimized like a multiplication by the number inverse, and in that case an integer division by 3 is 5 times faster than the float division).
An integer division by 2 is even faster, because it uses an arithmetic shift.
Borland's compiler uses extremely slow code to convert floats to integers (i don't understand why, but that is the case), so it is 5 times slower with float than with integers.
Conclusion : use float multiplications when variables are floats, and integer division when variables are integers.
Divison is the most expensive instruction to preform on any cpu, in other words its the most expensive instruction in the x86 language. I don't care what CPU you have, it's always going to be the slow instruciton because of the things the CPU has to do to get a result.
Don't put too much stock in open source compilers like MinGw. Compiler design is one of the hardest things to create. If you have a compiler that generates poorly optimized code or even no optimization, it's pointless to attempt to speed up anything. Take microsoft's standard edition of c++ .net. About every trick I'm showing is completely pointless to anyone who has that version of C++, because optmizations are not enabled in that compiler.
I think you're getting confused on what a jump table is. Select case statements do make a Table like looking code, however it's not the same thing I am talking about. Basically a variable is created to store offsets of every single label. So if you have 10 different things you want to test for, you would have a variable that is 10x4 bytes long. In each 4 bytes a memory location would be stored there, for each of the 10 items.
In asm it would looking something like this:
MyTable dd Label1, Label2, Label3, Label4, Label5, Label6, .... Label10
Then on down to where you would normally be making compares, you would simple say:
jmp [MyTabel+mytestvar]
Label1
....
...
..
Label2
...
...
..
And that one statement will automatically go to the code needed to be performed for that given input.
It's an optimization that compilers cannot really do because there is very special things that have to be met in order for it to work. In other words, you're tested input must be in some form of series and not random crap. If it was just a few numbers from 1 to 1,000,000, it would require 4x1,000,000 bytes to create the table just to perferm tests on a handful of numbers. It would be better in that case to use a different method.
-
Re: tips for optimizing vb code
Ok, seeing as this is a topic for code optamization.
Does anyone have any information in using GoTo's?
I use a few in my code and were wondering how they would affect the code :)
Cheers,
RyaNJ
-
Re: tips for optimizing vb code
Quote:
Originally Posted by sciguyryan
Ok, seeing as this is a topic for code optamization.
Does anyone have any information in using GoTo's?
I use a few in my code and were wondering how they would affect the code :)
Cheers,
RyaNJ
You should never use Gotos in code. It breaks the entire concept of structured programming.
-
Re: tips for optimizing vb code
Quote:
Originally Posted by Maven
You should never use Gotos in code. It breaks the entire concept of structured programming.
Maven - that wasn't the question!
With all the constructs available in VB - IF/THEN/ELSE, SELECT/CASE - boolean variables - looping - there are many better ways to flow through logic in VB than to use GOTO.
As far as speed - I can see no reason why GOTO would be faster than a properly coded IF/THEN/ELSE.
-
Re: tips for optimizing vb code
Quote:
Originally Posted by szlamany
With all the constructs available in VB - IF/THEN/ELSE, SELECT/CASE - boolean variables - looping - there are many better ways to flow through logic in VB than to use GOTO.
Still I've found (actually, very few) situations where a goto was the only way out I could think of. I just can't remember where I stored the specific example I have in mind, but I think it was something having to do with exiting from the innermost nested loop to one of the outer shelling loops.
-
Re: tips for optimizing vb code
Quote:
Originally Posted by krtxmrtz
Still I've found (actually, very few) situations where a goto was the only way out I could think of. I just can't remember where I stored the specific example I have in mind, but I think it was something having to do with exiting from the innermost nested loop to one of the outer shelling loops.
Thats exactly my point, it would be much too complex to do with out them (ANd I only use 4 of them dso don't fret ;))
I only wanted to know if they would effect the speed of the opperation abd by how much :)
I don't think it will have much effect seeing as I only use 4 anyway :)
Cheers,
RyanJ
-
Re: tips for optimizing vb code
Goinh back to the subject of slow division, might need some help here Maven:
Dividing without dividing
-
Re: tips for optimizing vb code
Is
with form
.text1.text = a
end with
Then same as
form1.text1.text = a
?
-
Re: tips for optimizing vb code
Quote:
Originally Posted by Krenshau
Is
with form
.text1.text = a
end with
Then same as
form1.text1.text = a
?
See this thread
http://www.vbforums.com/showthread.p...highlight=dots
Especially around post #30...
-
Re: tips for optimizing vb code
Quote:
Originally Posted by krtxmrtz
Still I've found (actually, very few) situations where a goto was the only way out I could think of. I just can't remember where I stored the specific example I have in mind, but I think it was something having to do with exiting from the innermost nested loop to one of the outer shelling loops.
I prefer to use Exit's over Goto statements where possible i.e.
Instead of using this
Code:
Public Sub Math(ByRef a as integer)
Select Case a
Case 1
a = a + 1
Case 2
b = b + 1
Goto DoMath
Case Else
' for other numbers
End Select
Exit Sub
DoMath:
' The only code that will work past here would be Case 2
a = a * b
I would rather use this
Code:
Public Sub Math(ByRef a as integer)
Select Case a
Case 1
a = a + 1
Exit Sub
Case 2
b = b + 1
Case Else
' for other numbers
Exit Sub
End Select
' The only code that will work past here would be Case 2
a = a * b
End Function
Thats just me though, sorry for messy code I wrote this in notepad heh
-
Re: tips for optimizing vb code
Quote:
I only wanted to know if they would effect the speed of the opperation abd by how much
I think he was referring to goto performance wise - goto will perform the same speed as if...then....else or perhaps faster in some cases - its actually just translated to the asm 'jmp' so it doesn't really have performance implications. The main thing most ppl complain about is that its jsut a bad programming practice.
I tend to disagree with the propaganda from these 'programming practices' but I tend to adhere to them for convenience sake and readability sake. Use Gotos when necessary and don't use them when unnecessary.
The main case where the goto wins on efficiency is when there is a internal nested loop or something and you need to get out of it - maybe going through two other loops. One way is to use if then and use flags to say the loop is terminated and i want to get out or just use a simple GOTO statment and get out. The latter would be the best approach - because it is faster and is only 1 line of code (and a 2nd line for the label). Other than that you probably manage all with if....then....else.
The above code with exit subs performance wise should actually be faster because it leaves the sub directly at each branch rather needing to jump.
-
Re: tips for optimizing vb code
Quote:
Originally Posted by dee-u
Unless disproved by others I believe these would also optimize vb code
using textbox = 'your text' over textbox.text = 'your text'
using label = 'your caption' over label.caption = 'your caption'
etc....
etc....
I disagree on leaving the compiler to fill in the default to speed up your code
because that is what happens the compiler generate's the same code anyways and it isn't faster unless you add typing code to the equasion :bigyello:
A serious speed tip for arrays
if you want to delete or insert an item in an array with fixed lenght items like longs,
bytes, fixed length array or UDT made out of these types use memcopy to shift the values:
example for a array of longs
VB Code:
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(dest As Any, source As Any, ByVal numBytes As Long)
Sub InsertItemToLongArray(LongArr() As Long, Index As Long, NewItem As Long)
' using LenB() to evaluate size so it can be used easily for other type
' arrays just by altering the argument types (in speed critical circumstances
' you can hardcode these lengths ofcourse)
If Index < UBound(LongArr) Then
CopyMemory LongArr(Index + 1), LongArr(Index), (UBound(LongArr) Index) * LenB(LongArr(Index))
End If
LongArr(index) = NewItem
End Sub
Sub DeleteItemFromLongArray(LongArr() As Long, Index As Long)
If index < UBound(LongArr) Then
CopyMemory LongArr(Index), LongArr(Index + 1), (UBound(LongArr) - Index) * LenB(LongArr(Index))
End If
LongArr(Index) = vbEmpty
End Sub
NOTE: do not use this for arrays containing Objects, Dynamic Strings UDT's containing these kind of objects. It will bring the app down for sure.
-
Re: tips for optimizing vb code
I'd just like to point out that there is a HUGE difference between a for loop and a Do loop in visual basic. I found this out in my younger days while trying to debug something. My code was something similar to (but obviously not as stupid as):
VB Code:
public function something(byval s as string) as boolean
dim A as long
for a = 1 to len(s)
s = left(s, len(s) - 1)
next a
end function
Now, granted the code calculates len(s) constantly in the loop, but my problem was it kept giving me out of bounds errors. It turns out that a for loop STORES THE VALUE OF LEN(S) at the start and then loops through! You get the same thing when you use the "With" command.
Try this code out as well:
VB Code:
'In Class1
Option Explicit
Public Name As String
'In a form
Option Explicit
Private Sub Form_Load()
Dim A As Class1
Dim B As Class1
Dim C As Class1
Set A = New Class1
Set B = New Class1
A.Name = "A"
B.Name = "B"
Set C = A
With C
Set C = B
MsgBox .Name
End With
End Sub
"A" pops up.
-
Re: tips for optimizing vb code
The for loop thing is just a normal behavior for a loop: there is just no point recalculating the value. This also makes for loop faster (= a more efficient choice) than do loop in some situatations.
I don't see anything wrong with the With statement either, because that's just how it works: With will Reference to class A since C is just a reference to class A; or more so exactly the same as class A. This clarifies why With statement works as it does:
VB Code:
Option Explicit
Private Sub Form_Load()
Dim A As Class1
Dim B As Class1
Dim C As Class1
Set A = New Class1
Set B = New Class1
A.Name = "A"
B.Name = "B"
Set C = A
With C
Set C = B
.Name = "1"
C.Name = "2"
MsgBox "A: " & A.Name & " - B: " & B.Name
End With
End Sub
-
Re: tips for optimizing vb code
Quote:
Originally Posted by Merri
The for loop thing is just a normal behavior for a loop: there is just no point recalculating the value. This also makes for loop faster (= a more efficient choice) than do loop in some situatations.
I don't see anything wrong with the With statement either, because that's just how it works: With will Reference to class A since C is just a reference to class A; or more so exactly the same as class A. This clarifies why With statement works as it does:
VB Code:
Option Explicit
Private Sub Form_Load()
Dim A As Class1
Dim B As Class1
Dim C As Class1
Set A = New Class1
Set B = New Class1
A.Name = "A"
B.Name = "B"
Set C = A
With C
Set C = B
.Name = "1"
C.Name = "2"
MsgBox "A: " & A.Name & " - B: " & B.Name
End With
End Sub
Yes yes, I know that's how it works and appreciate. I was just pointing it out for everyone. I found the With behavior very "huh?!" at first. I thought the compiler was just adding the "c" back in front.
-
Re: tips for optimizing vb code
Maybe it would be better to point it out in the FAQ forum instead of a thread dedicated for optimization? Atleast that'd make it clear for us to understand you're pointing out something and not wondering it :)