PDA

Click to See Complete Forum and Search --> : tips for optimizing vb code


Maven
Dec 9th, 2004, 12:22 AM
There is only so much you can do with optimizing vb code. The largest reason for this is due to visual basic hiding so much from us and of course the lack of “umph” in the language itself. If you want lighting fast code then you really have no choice but to write a dll file in another language and calling it from visual basic. I'm not going to go down that road in this tutorial but attempt to show you a few methods to help speed up visual basic code. Hopefully this tutorial will help a few of the newer programmers and also teach the old ones a few new tricks =)

A few Notes:
It's important to know the compiler options of visual basic. You want to compile to native code and not p-code. P-code stands for pseudo code, which means that your instructions will be translated at runtime and will make your program run a lot slower. You also have more options when you compile to native code. One of the big ones is:
“Assume No Aliasing (Advanced Optimization)”. If your not passing variables via byref then always check that. Microsoft warns that if you have variables passed byref to functions that it could cause the code to run incorrectly. In a nutshell, no matter what language you use, always read up on the compiler options. You can read more about visual basics compiler options in the msdn library.

One thing I suggest all programmers do is to learn assembler. If you don't know it, then you should add “Learn Assembler” on you're todo list. Don't go for online tutorials either, you should buy a good book and not put it down till you know how to write ASM. You simply don't know how things work until you know assembler and knowing how things work is a must to writing fast code. Assembler is where you unlock all the secrets that I'm sure you've asked at some point. It's where you learn “Why”.

Creating fast code does have a few drawbacks. Code that is optimized can be very cryptic** to read. So make sure you always comment optimized code well, or you may find yourself thinking “What was I doing here?”. Another drawback is program size. You may find yourself making program size vs program speed decisions.

Before you sit down and start optimizing code, you first need to do something. That is, you need to identify the critical parts of your code. In other words, you need to identify the code that NEEDS optimizing. Loops and complex calculation algorithms are the two most important things to look at. Many programmers have completely wasted their time by optimizing things in their application that doesn't mean squat. You also need to know that you cannot optimize code that isn't yours. For example, you cannot optimize code in the windows API or 3rd party controls that your application uses. When you're working with 3rd party stuff, there is very little you can do short of re-writing it.

Use the GetTickCount API to time your code, though you may have to loop some of it quite a bit to see the effects of it. I may try to write a dll in asm later on that makes use of the rdtsc instruction, that you would be able to call from visual basic and get clock cycles that your code uses. If I manage to get it to work with visual basic it would be better to profile your code with it as you wouldn't need gettickcount or have to loop your code a lot. It's a very exotic feature that would be nice to have in visual basic.

Enough of the notes, lets start learning code optimization.

Tip #1 – Move as much code as possible outside of loops.
Loops are always the most important thing to optimize in your code. Always try to move as much as you can out of a loop. That way code doesn't get repeated and saves you some cpu cycles. A simple example:


for i = 1 to 50
x = b ' Stays the same with every loop, get it outside of the loop!
k = j + i
next i


Change that to:


x = b 'Moved outside the loop

for i = 1 to 50
k = j + 1
next i

That may seem like a no-brainier but you would be surprised about how many programmers do that. The simple rule is, if it doesn't change with every loop iteration then move it outside of the loop as it doesn't need to be there. You only want to include code inside a loop that MUST be there. The more instructions you can clear out of a loop the faster we can run it.

Tip #2 – Loop Unrolling
Loop unrolling can eliminate some compare and jump instructions. (Compare and jump instructions are used to create loops, you don't see them in visual basic, its behind the scenes stuff that you learn in ASM.) It also takes advantage of the ability of modern cpus that can fetch several instructions at a time. In a nutshell you get a good speed boast by unrolling loops.

But there is something we need to know about loop unrolling. The largest bottleneck on modern computers is memory. So the designers of CPU's like Intel and AMD addressed this problem by using a cache on their cpus. This is basically a memory location that is accessed much faster by the CPU then standard memory. You want your unrolled loop to fit in that cache, if it doesn't then it could slow down your code. So you may want to experiment with gettickcount when you unroll you're loop.

Example Loop:

For i = 1 To 100
b = somefun(b)
Next i

unrolled Example:

For i = 1 To 100 step 2
b = somefun(b)
b = somefun(b)
Next i

You can get up to a 25% gain in speed depending on what you are doing, you just have to experiment with this.

Tip #3 – Avoid dividing if possible.
A divide instruction is one of the most if not the most expensive instruction you can perform on a CPU. It is faster to multiply then divide!


B = 40 / 2

is slower then

b = 40 * 0.5

You can also develop some interesting algorithms using subtraction to get your result that is much faster then using division. If your using division in a loop, it is a must to change it to speed up your code. (I was going to also recommend trying shifting the bits for division but I forgot some versions of visual basic doesn't include the shift operator).

Tip #4 – In a nested conditional branch such as select case and nested if statements, put the things that are most likely to be true first in the nest, with the least likely things last.

Tip #5 – Avoid use of variant variables.
The variant variable is all nice when you are new to visual basic, but its a habit you need to break. A variant variable is converted into its proper data type at runtime which can be very expensive.

Tip #6 – Be careful when you declare variables.
If you don't use as something with every variable you declare, it is a variant! For example:

Dim a, b, c as string.
A = A variant
B = A variant
C = A string


I've seen some people use the notation:

dim x
x = blah

that is a NO NO! It may work yes, but its going to cost you speed.

Tip #7 – Reduce common expressions.
Sometimes you have two different variables that use part of the same calculation. Instead of doing the entire calculation for both variables, eliminate the redundant calculation.

Example:

x = a * b + c
y = a * b + d

is slower then

t = a * b
x = t + c
y = t + d

That is especially true if your using a redundant expensive calculation in a loop.

Tip # 7 – Use long or integer for calculations.
A long is a 32 bit number and is more natural on 32 bit processors. Avoid other variables such as double, single, etc

Tip #8 – Use inline functions inside of loops.
Instead of calling a function, stick the code in the loop. This will make you're program larger if you repeat it in enough loops and should only be done in critical places. The reason is due to the over head of calling a function. Before the program calls a function, it has to push some things onto the stack. At the very least it will push the instruction pointer (IE: Return Address). Memory access is slow so we want to avoid that in critical places.

Tip #9 Avoid using properties in loops.
Properties are accessed a lot slower then variables, so use variables instead:


for i = 1 to 50
text1.text = text1.text + b(i)
next i

is slower then

for i = 1 to 50
strbuffer = strbuffer + b(i)
next i
text1.text = strbuffer

Tip #10 – Load all the data you need from the disk.
Instead of loading one file at a time, load all of them at once. This will avoid future delay for the user.

Tip #11 – Make good use of the timer control.
You can do background processing while waiting on a user. Use this time to prefetch data, calculations that are need, etc.

Tip #12 – Minimize dot notation in your objects!
Each dot you use in a object makes visual basic do a call.


Myobject.one.two.three

is slower then

Myobject.one

Tip #13 Allocate enough memory at once.
When you create a dynamic array and you want to add elements that haven't been allocated yet, make sure you allocate enough for all of them instead of doing it one at a time. If you don't know how many you need, times what you have allocated by 2. Allocating memory is a expensive process.

Tip #14 Avoid built in functions in loops.
If you have a algorithm that is looped that requires the len of your string. Make sure you cache the size of your string in a buffer and not call the function len() with each iteration of the loop:

for i = 1 to 100
sz = len(string)
'Do processing
next i


instead


sz = len(string)
for i = 1 to 100
'Do Processing with sz
next i


Tip #15 Hide the control when your setting its properties.
Every time you update the properties of your control, you make it repaint. So if your developing something that displays complex graphics, may be a good idea to reduce that from happening so much.

Maven
Dec 9th, 2004, 12:23 AM
lol I didn't know you could only post a max of 10000 charecters =P

=/ I'm long winded

si_the_geek
Dec 9th, 2004, 04:36 AM
Good stuff :thumb:

Merri
Dec 9th, 2004, 05:39 AM
I'd complain about this:

for i = 1 to 50
strbuffer = strbuffer + b(i)
next i
text1.text = strbuffer


You should use & instead :)


Also, it would've been nice if you used [ code ] tags to separate the code. Proper formatting would have been nice, too:


For i = 1 To 50
strBuffer = strBuffer & b(i)
Next i
Text1.Text = strBuffer


:)



I have some extreme tips here:

- LenB is faster than Len (though gives result in bytes instead of characters = two times bigger)
- byte arrays are faster to handle than strings: avoiding string processing gives very good results when we start going to Real Speed with VB6
- simple math functions in VB are just as fast they are in C++


Note: I haven't learned ASM as I can do pretty fast code with pure VB. It is only a matter of looking for the fastest things you can do :)



Edit More things to the article itself:

Tip #3 – Avoid dividing if possible.
A divide instruction is one of the most if not the most expensive instruction you can perform on a CPU. It is faster to multiply then divide!

B = 40 / 2

is slower then

b = 40 * 0.5

But \ is The Fastest!

B = 40 \ 2 is faster than doing * 0.5

Maven
Dec 9th, 2004, 11:01 AM
I'd complain about this:

for i = 1 to 50
strbuffer = strbuffer + b(i)
next i
text1.text = strbuffer


You should use & instead :)


Also, it would've been nice if you used [ code ] tags to separate the code. Proper formatting would have been nice, too:


For i = 1 To 50
strBuffer = strBuffer & b(i)
Next i
Text1.Text = strBuffer


:)



I have some extreme tips here:

- LenB is faster than Len (though gives result in bytes instead of characters = two times bigger)
- byte arrays are faster to handle than strings: avoiding string processing gives very good results when we start going to Real Speed with VB6
- simple math functions in VB are just as fast they are in C++


Note: I haven't learned ASM as I can do pretty fast code with pure VB. It is only a matter of looking for the fastest things you can do :)



Edit More things to the article itself:



But \ is The Fastest!

B = 40 \ 2 is faster than doing * 0.5


I'll format the code after this post.

No matter what you do really, even optimized code is very slow in visual basic expecially if you compared it to ASM. You don't really have any restrictions in ASM, you can load up 4 charecters of a string in a integer if you want to.

Multiplication is faster then division on most processors:

Private Declare Function GetTickCount Lib "kernel32" () As Long

Private Sub Command1_Click()
Dim start As Long
Dim finish As Long
Dim i As Long
Dim b As Long

start = GetTickCount
For i = 1 To 1000000
'b = 40 * 0.5
b = 40 / 2
Next i
finish = GetTickCount

Debug.Print (finish - start)
End Sub


A division instruction is 50 clock cycles, which is crazy! lol.

Merri
Dec 9th, 2004, 11:32 AM
But \ is still faster, it isn't a division: it just counts how many times the given number fits in the other given number :)

I had to make the loop bigger because the values were too small. GetTickCount is getting accurate enough at hundreds. This is tested with uncompiled code:
/ - 750
* - 560
\ - 375


You shouldn't compare ASM and VB. You can do some comparison between C++ and VB. ASM and VB work on so different level of development that you shouldn't compare their speed - VB's strong point is at rapid development, ASM is powerful but very slow to code. Instead, you should concentrate doing VB as fast as you can (when the speed matters). I'm unlikely to touch to ASM at the moment or anytime soon, as VB's optimized speed is enough for my needs - the same goes for many other people, they're unlikely to learn a new language just to make one thing working, say, 10% faster on ASM than what they can get at best with VB (though, many people don't get their code that fast with VB, because speed optimization requires studying and experience a lot).

Maven
Dec 9th, 2004, 12:00 PM
But \ is still faster, it isn't a division: it just counts how many times the given number fits in the other given number :)

I had to make the loop bigger because the values were too small. GetTickCount is getting accurate enough at hundreds. This is tested with uncompiled code:
/ - 750
* - 560
\ - 375


You shouldn't compare ASM and VB. You can do some comparison between C++ and VB. ASM and VB work on so different level of development that you shouldn't compare their speed - VB's strong point is at rapid development, ASM is powerful but very slow to code. Instead, you should concentrate doing VB as fast as you can (when the speed matters). I'm unlikely to touch to ASM at the moment or anytime soon, as VB's optimized speed is enough for my needs - the same goes for many other people, they're unlikely to learn a new language just to make one thing working, say, 10% faster on ASM than what they can get at best with VB (though, many people don't get their code that fast with VB, because speed optimization requires studying and experience a lot).

If your going to compare languages just for the sake of it, it would be more fair to visual basic if you compared it with delphi then C++.

You do asm to speed things up more then anything. You don't do entire applications in ASM, just critical areas that must have speed. If you don't do this then you will always be limited to what you can do with visual basic. The gap between asm and visual basic is a lot more then 10%, its more like 90% at least.

Merri
Dec 9th, 2004, 12:57 PM
Depends what you're doing. For example, doing a highly efficient 3D-engine in ASM would be superb, it would work even on a lower class machine and doing similar with C/C++, Delphi or VB would be hard for the least. The only thing in the way is the development time. But on the topic, this would be a lot faster.

For simple math processing, you can't do much better than what the basic commands do. 1 + 1 is fast whatever language you use, even though ASM has its own way on it. You can do things in the best possible way in ASM, but it gets maybe too detailed for a "normal" programmer. ASM is a solution, but only for rare, special cases.


We could try doing something simple as fast as possible with each language to see the real differences.

Comintern
Jan 7th, 2005, 02:55 PM
OK, here's one I've never seen before. From the speed tests I've been running, it seems to cost a lot of speed to use the built-in VB date functions when working with times. These two code snippets are functionally the same, and Format() returns correctly when passed the double.

Public Const cYEAR = 365.25
Public Const cDAY = 1
Public Const cHOUR = 1 / 24
Public Const cMINUTE = cHOUR / 60
Public Const cSECOND = cMINUTE / 60

Dim dDouble As Double

dDouble = Now + (cSECOND * 123)

The code above is about 5 times faster than the code below:

Dim dDate As Date

dDate = DateAdd("s", 123, Now)

Even when wrapped in a function like this, the overhead for calling the function is only accounting for about a 20% loss.

Private Function SecondAdd(dDouble As Double, iSeconds As Integer) As Double

SecondAdd = dDouble + (iSeconds * cSECOND)

End Function

The only one that is kind of tricky is the year (because of leap years), but it seems to work to multiply by 365.25 and only keep the integer.

dDouble = Now + CInt(cYEAR * 12)

NoteMe
Jan 7th, 2005, 05:57 PM
Depends what you're doing. For example, doing a highly efficient 3D-engine in ASM would be superb, it would work even on a lower class machine and doing similar with C/C++, Delphi or VB would be hard for the least. The only thing in the way is the development time. But on the topic, this would be a lot faster.

For simple math processing, you can't do much better than what the basic commands do. 1 + 1 is fast whatever language you use, even though ASM has its own way on it. You can do things in the best possible way in ASM, but it gets maybe too detailed for a "normal" programmer. ASM is a solution, but only for rare, special cases.


We could try doing something simple as fast as possible with each language to see the real differences.


The point is that in a lower level langauge you can use diffrent instruction set that VB don't use. Like for caluclations and multimedia you can use SSE, SSE2, and MMX instructions that VB never will use.

tr333
Jan 7th, 2005, 10:19 PM
Tip # 7 – Use long or integer for calculations.
A long is a 32 bit number and is more natural on 32 bit processors

A long is a 64 bit number.

Maven
Jan 7th, 2005, 10:56 PM
A long is a 64 bit number.

Long is 32 bit with one exception. When you run .net on a 64 bit platform it will be 64.

Merri
Jan 8th, 2005, 02:05 AM
The point is that in a lower level langauge you can use diffrent instruction set that VB don't use. Like for caluclations and multimedia you can use SSE, SSE2, and MMX instructions that VB never will use.

Which also means you're limiting the number of computers the code will work on. Of course you could make different code for different instruction sets, but that might require a lot of extra coding... worth it if you're doing something like video and sound manipulation, but near useless if it is for a game loop. Huge time consuming calculations are also something not done by everybody. To have a reason to spend time to code with lower level language such as ASM, you really need to think if it is worth the time spent to the coding, because it does take a lot of time.

The point you said doesn't change the situatation much at all: low level language stays a something for rare special occasions. If it was more worth the time, more people would be using it often.

NoteMe
Jan 8th, 2005, 11:54 AM
Which also means you're limiting the number of computers the code will work on. Of course you could make different code for different instruction sets, but that might require a lot of extra coding... worth it if you're doing something like video and sound manipulation, but near useless if it is for a game loop. Huge time consuming calculations are also something not done by everybody. To have a reason to spend time to code with lower level language such as ASM, you really need to think if it is worth the time spent to the coding, because it does take a lot of time.

The point you said doesn't change the situatation much at all: low level language stays a something for rare special occasions. If it was more worth the time, more people would be using it often.


All games are using it...;)...even books on DX and OGL. And even dumb me is using it when programming games...;)

szlamany
Jan 8th, 2005, 02:34 PM
Long is 32 bit with one exception. When you run .net on a 64 bit platform it will be 64.

This is absurd - leave it to MS to create a new datatype - SHORT - then reassign INTEGER (which isn't even a datatype!) to 16 bit and LONG to 64 bit.

DEC had it right - and simple. BYTE was 8, WORD was 16, LONG was 32 and when they created there 64-bit architecture we got QUADWORDS.

What's MS going to do when 128-bit chips are out?

NoteMe
Jan 9th, 2005, 10:23 AM
OctWord?

Merri
Jan 9th, 2005, 12:33 PM
8-bit: BITS
16-bit: BYTES
32-bit: SHORT
64-bit: INTEGER
128-bit: LONG
256-bit: HEAVY
512-bit: DECIMAL
1024-bit: VARIANT
2048-bit: XXXL

This is the future.

szlamany
Jan 9th, 2005, 12:35 PM
8-bit: BITS
16-bit: BYTES
32-bit: SHORT
64-bit: INTEGER
128-bit: LONG
256-bit: HEAVY
512-bit: DECIMAL
1024-bit: VARIANT
2048-bit: XXXL

This is the future.

Bill should have just asked you in the first place - you have true vision :bigyello:

Maven
Jan 9th, 2005, 02:13 PM
Bill should have just asked you in the first place - you have true vision :bigyello:

BYTE
WORD
DWORD
QUADWORD
TENBYTE

timeshifter
Jan 10th, 2005, 12:39 PM
8-bit: BITS
16-bit: BYTES
32-bit: SHORT
64-bit: INTEGER
128-bit: LONG
256-bit: VERYLONG
512-bit: VERYVERYLONG
1024-bit: SEPTBIT
2048-bit: OCTBIT

...continue as you see fit. Personally, I think we should move into:

8192-bit: VERYVERYVERYVERYLONG

There's your future.

nareth
Jan 18th, 2005, 11:28 AM
how can you call 8 bit 1 bit.... lol

Otac0n
Jan 25th, 2005, 03:34 PM
how can you call 8 bit 1 bit.... lol

He didnt, he called it "BITS"

Plural

System_Error
Feb 14th, 2005, 06:14 PM
I'm curious why would division be slower than all the other arithmetic operations...and, is this only in vb.net, or does this apply to every language?

Also, what would you do if you were creating a calculator?

NoteMe
Feb 14th, 2005, 07:29 PM
I'm curious why would division be slower than all the other arithmetic operations...and, is this only in vb.net, or does this apply to every language?


That depends on what instruction codes you can write for in that language. And it also depends on what kind of datatype you are using.


Also, what would you do if you were creating a calculator?


I have seen your work in the Java section. Good stuff, keep it up.

Well it will depend on what you want to do. If speed is the ultimate goal you will do it the fast way, but not always the most accurate way. If you want the accuracy but don't care that much for the speed, then you will do the most accurate way, and not care about the speed.


In a calculator you often want it accutate, and don't care if it takes a few ms more then the other way (that even might be more error prone). So if you need Sqrt() or / in your calculator, you will often use that, and not some fancy Carmack code to get the job done.


Hope that helped.
ØØ

Maven
Feb 15th, 2005, 03:27 AM
I'm curious why would division be slower than all the other arithmetic operations...and, is this only in vb.net, or does this apply to every language?

Also, what would you do if you were creating a calculator?

It's slower in every language, not just VB. The reason it's slower is because there is a lot of steps to do when doing division. Basically intel and amd wrote the best general division algorithm they could come up with. You can beat it, but not in all cases. You can always go download the intel docs from their site and see their algorithm for the division instruction. Just know those docs may be a little over-head of some visual basic programmers.

If you have bitwise operators in a language, it's faster to use them for divison and multiplicaiton where you can. Like shift right 1, is divide by 2. I'm thinking vb.net does but i"m not for sure.

Loop Unrooling is another thing that apply's to all languages. In fact you're likely to get a better speed up in other languages like C++ and java then visual basic using that trick.

--------

I wouldn't think you would need to worry about optimizing a calcualtor. Then again if you're doing some kind of scientific calcualtor, it may be worth the time. The only time I really worry about a divison instruction is when it is inside a loop. I do my best to move it outside a loop. Loops are really what you want to pay special attention to in any language. A divison instruction inside a loop will burn you're speed up fast. Most of the time, it takes more time to execute that one divsion instruction then the rest of the code in a loop. A lot of compare statements in a loop is something I go after too. Like a very long switch statement (Select case in vb doh). 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.

Before someone asks how that is possible...
Basically I create what is called a JUMP table. I create all the labels I need and store the offsets in a variable. I then basically offset that variable with what ever number I'm given to search for and then jump to the offset stored in that location in memory. So basically, it's looks at a memroy address for a pointer to the code required to execute that certain event and jump to it.

System_Error
Feb 15th, 2005, 05:08 AM
Thank you Maven and NoteMe, preciate the feedback!

dee-u
Feb 27th, 2005, 07:22 PM
Isnt

For i = 1 To ...
...
Next

faster than

For i = 1 To ...
...
Next i

Merri
Feb 28th, 2005, 07:33 PM
No difference at all. Such things do not matter because the code gets compiled and the variable is "added" there by compiler when it processes the code.

dee-u
Mar 8th, 2005, 09:34 PM
Is this code
Dim x as integer,a as integer
x=listbox.count-1
for a= 0 to x
next a

faster than

Dim a as integer
for a= 0 to listbox.count-1
next a

dglienna
Mar 8th, 2005, 11:30 PM
yes, because the value would have to be calculated for each iteration of the loop in the second instance, which takes time.

Maven
Mar 9th, 2005, 01:35 AM
yes, because the value would have to be calculated for each iteration of the loop in the second instance, which takes time.

Not to mention you'd be using a function call with each iteration of a loop. Every single dot you use, is a call. So more dots, more time.

Merri
Mar 9th, 2005, 09:39 AM
Actually, that is untrue there: for loops can be and are optimized in this case, because they know how much to do: the values given are "static". It doesn't recount the value in each iteration. If you used a Do... Loop, then there would be a check each time. Do Loop is generally faster than For Next, except in this particular case when using a "static" value. If you need to do from A to B, use For Loop. For anything else Do Loop is likely to be faster.

wossname
Mar 10th, 2005, 03:25 AM
Actually, that is untrue there: for loops can be and are optimized in this case, because they know how much to do: the values given are "static". It doesn't recount the value in each iteration. If you used a Do... Loop, then there would be a check each time. Do Loop is generally faster than For Next, except in this particular case when using a "static" value. If you need to do from A to B, use For Loop. For anything else Do Loop is likely to be faster.

MSDN says there is no significant difference between Do and For.

dee-u
Mar 14th, 2005, 06:35 AM
Unless disproved by others I believe these would also optimize vb code

using chr$ over chr
using mid$ over mid
using left$ over left
using right$ over right
etc....

using textbox = 'your text' over textbox.text = 'your text'
using label = 'your caption' over label.caption = 'your caption'
etc....

using textbox = vbnullstring over textbox = ""
using label = vbnullstring over label = ""
etc....

using command_click over command.value = true
etc....

szlamany
Mar 14th, 2005, 06:59 AM
I agree - but they really fall into the realm of best practices.

What you have can be summed up with:

1) Do not use VARIANT datatypes when other datatypes are appropriate.
2) Do not use FUNCTIONS that return VARIANT datatypes.
3) Use CONSTANTS (self-declared or VB standard) instead of literal values when possible.

I'm not sure everyone would agree with use TEXTBOX = instead of TEXTBOX.TEXT = . In general, it is not a best practice to use DEFAULT PROPERTIES.

plenderj
Mar 14th, 2005, 07:01 AM
using chr$ over chr
using mid$ over mid
using left$ over left
using right$ over right


Correct as they return Variants by default, whereas appending the dollar sign will cause it to return a String.


using textbox = 'your text' over textbox.text = 'your text'
using label = 'your caption' over label.caption = 'your caption'


I don't agree. I think its bad coding practice to make use of defauly properties.
Looks nicer sometimes though :)


using textbox = vbnullstring over textbox = ""
using label = vbnullstring over label = ""
etc....


I would agree.

wossname
Mar 14th, 2005, 07:29 AM
I don't agree. I think its bad coding practice to make use of defauly properties.


In VB6 I would also agree on this point. But it it not the case with VB.Net, which has Default properties and tight rules about their use. They generally tend to be a wrapper for some internal array or function or something like that. They can be extremely useful and in many cases it is quite obvious that a default property is being used.

Just thought I'd add that in case any VB6-->.Net newbies get into the habit of disliking default properties and bring that belief with them to .net :D

plenderj
Mar 15th, 2005, 03:17 AM
Oh don't be so arrogant ;)

wossname
Mar 15th, 2005, 05:08 AM
My middle name is Supercillious.

Merri
Mar 17th, 2005, 04:04 AM
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:


'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...

wossname
Mar 17th, 2005, 06:35 AM
That is not a fair test though for at least 3 reasons I can see.

This is a less biased benchmark...


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)

szlamany
Mar 17th, 2005, 06:49 AM
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!

Maven
Mar 17th, 2005, 01:51 PM
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.

dee-u
Mar 29th, 2005, 06:44 PM
This might also be of help to vb coders:
http://www.codeguru.com/forum/showthread.php?t=327355&highlight=speed

Maven
Mar 30th, 2005, 03:26 AM
This might also be of help to vb coders:
http://www.codeguru.com/forum/showthread.php?t=327355&highlight=speed

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.

krtxmrtz
Apr 14th, 2005, 06:10 AM
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:


'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:

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

szlamany
Apr 14th, 2005, 06:55 AM
However I have found just the opposite for similar 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.

krtxmrtz
Apr 14th, 2005, 07:37 AM
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?

szlamany
Apr 14th, 2005, 07:40 AM
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.

krtxmrtz
Apr 14th, 2005, 07:51 AM
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:

'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.

Maven
Apr 14th, 2005, 12:01 PM
You bet. This is it:

'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.

krtxmrtz
Apr 15th, 2005, 05:21 AM
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.

longwolf
Apr 29th, 2005, 03:45 PM
Another tip for your loops
<= is slower than =

so you might retest the speed of the Do loop again using this

'add an extra point to iter
iter = 100000001
Do Until i = iter
j = i
i = i + 1
Loop

Max_aka_NOBODY
Apr 29th, 2005, 04:10 PM
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.

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.

Jacob Roman
May 1st, 2005, 10:27 PM
Another tip that must be added, Maven.

Single line If statements


If X >= 100 Then X = 0


is faster than Block If's


If X >= 100 Then

X = 0

End If

Max_aka_NOBODY
May 1st, 2005, 10:30 PM
And IIf is the slowest BTW.

Jacob Roman
May 3rd, 2005, 09:11 PM
Yup. Also, weren't ElseIf statments faster than Select Case? We proved that in this one thread.

|2eM!x
May 3rd, 2005, 10:49 PM
i think that was my thread^^

Dreamlax
May 3rd, 2005, 11:11 PM
Yup. Also, weren't ElseIf statments faster than Select Case? We proved that in this one thread.

Case:
Select Case a
Case 10: MyFunc
Case 14: YourFunc
Case 15: Beep 'For arguments sake.
End Select

If:

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:

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):


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.

SuperKoko
May 23rd, 2005, 05:53 AM
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.

SuperKoko
May 23rd, 2005, 06:31 AM
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.

Maven
May 24th, 2005, 03:55 AM
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.

sciguyryan
May 24th, 2005, 06:14 PM
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

Maven
May 25th, 2005, 03:03 AM
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.

szlamany
May 25th, 2005, 05:13 AM
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.

krtxmrtz
May 25th, 2005, 06:07 AM
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.

sciguyryan
May 25th, 2005, 08:35 AM
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

Jacob Roman
May 25th, 2005, 02:28 PM
Goinh back to the subject of slow division, might need some help here Maven:

Dividing without dividing (http://www.vbforums.com/showthread.php?t=339655&highlight=Dividing+dividing)

Krenshau
Jun 17th, 2005, 01:27 PM
Is

with form

.text1.text = a

end with

Then same as

form1.text1.text = a

?

szlamany
Jun 17th, 2005, 01:38 PM
Is

with form

.text1.text = a

end with

Then same as

form1.text1.text = a

?

See this thread

http://www.vbforums.com/showthread.php?t=335783&highlight=dots

Especially around post #30...

Nevo
Dec 12th, 2005, 07:19 AM
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


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


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

Raedwulf
Dec 16th, 2005, 01:52 AM
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.

Dnereb
Dec 16th, 2005, 03:48 AM
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

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.

alkatran
Dec 29th, 2005, 12:01 AM
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):


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:


'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.

Merri
Dec 29th, 2005, 07:54 AM
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:

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

alkatran
Dec 29th, 2005, 01:40 PM
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:

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.

Merri
Dec 30th, 2005, 01:56 AM
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 :)