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!
*** Read the sticky in the DB forum about how to get your question answered quickly!! ***
Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".
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.
Education is an admirable thing, but it is well to remember from time to time that nothing that is worth knowing can be taught. - Oscar Wilde
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.
Education is an admirable thing, but it is well to remember from time to time that nothing that is worth knowing can be taught. - Oscar Wilde
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
Lottery is a tax on people who are bad at maths
If only mosquitoes sucked fat instead of blood...
To do is to be (Descartes). To be is to do (Sartre). To be do be do (Sinatra)
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.
*** Read the sticky in the DB forum about how to get your question answered quickly!! ***
Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".
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?
Lottery is a tax on people who are bad at maths
If only mosquitoes sucked fat instead of blood...
To do is to be (Descartes). To be is to do (Sartre). To be do be do (Sinatra)
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.
Lottery is a tax on people who are bad at maths
If only mosquitoes sucked fat instead of blood...
To do is to be (Descartes). To be is to do (Sartre). To be do be do (Sinatra)
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.
Education is an admirable thing, but it is well to remember from time to time that nothing that is worth knowing can be taught. - Oscar Wilde
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.
Lottery is a tax on people who are bad at maths
If only mosquitoes sucked fat instead of blood...
To do is to be (Descartes). To be is to do (Sartre). To be do be do (Sinatra)
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.
Please, put a checkmark ( ) or the word [RESOLVED] in your topic title if it was resolved, and rate the person who resolved it.
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.
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.
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).
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:
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.
Education is an admirable thing, but it is well to remember from time to time that nothing that is worth knowing can be taught. - Oscar Wilde
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.
*** Read the sticky in the DB forum about how to get your question answered quickly!! ***
Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".
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.
Lottery is a tax on people who are bad at maths
If only mosquitoes sucked fat instead of blood...
To do is to be (Descartes). To be is to do (Sartre). To be do be do (Sinatra)
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
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
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.
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
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
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.
Don't pay attention to this signature, it's contradictory.
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:
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.
Don't pay attention to this signature, it's contradictory.
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