I've been obsessed lately with performance tweaks.
Some of the things I have done more than likely are more costly in
programming effort than will ever be saved during execution but I thought I
would share some ideas, thoughts, and wonderings while waiting for the clock
to hit 12:30 so I can leave for the long week end (PS Happy New Year to all).
Functions and Subs - Some time ago, I got into a very bad habit of trying to
plan ahead during programming and instead of thinking out the process
completely, I would always use Functions instead of Subs. This led to a
number of places where, when I didn't really have a return, that I left off
the return type. I assume that this compiles so that a variant return code
is created which of cource, was never set or checked either. I also found
that I had a number of functions that I returned a success or failure from
that, frankly would never fail (short of memory short-circuiting or the PC
catching on fire). These, I converted to subs.
I'm also adding very specific control over how a form gets displayed by
showing what can be shown quickly and, if necessary, even showing a temporary
box that says "loading..." where some lengthy process might be filling a grid.
I'm always using integer instead of longs unless I'm not sure interger will
be sufficient. This is one I wonder about in a 32 bit app.
I have also experimented with using static variables in most places (where
they are initialized anyway) as opposed to dimming new variables. I've read
conflicting opinions on what method is faster but it seems to me that with
static, even though the scope is local only to the procedure, it still has to
be kept and maintained somehow. This is another one I wonder about
especially when you add in intagibles such as available memory and
application size and degree of swapping and even operating system differences.
Use of the With...End With structure. I know this normally will speed up
processing but will slow things down if there isn't enough referencing being
saved.
Here is one I want to try sometime... lets say you have a couple of big
UDTs and you want to pass values between them. You can use the With...End
with structure nicely with this but consider the following:
This is obvious
=========
With myThing
.variable1 = myOtherThing.Variable1
etc
end with
But what if MyThing and myOtherthing both had long sets of dots each. for
example:
Mything.this(x).that(y).theOther.foo = MyOtherThing.this(x).that(y).bar
Would this improve performance?
set X = MyOtherThing.this(x).that(y)
with Mything.this(x).that(y).theOther
.foo = x.bar
etc
end with
...be faster?
I use the dictionary object a lot but I wonder if it might be faster to have
a class of something with all of the dictionary objects features with my own
item and key and then create arrays of this object? The obvious advantage is
that you could add custom mthods and functions not available in a dictionary
object not to mention having extra 'item' fields available. Anyone played
with this and checked performance?
Brian Schwartz - 30 Dec 2004 20:12 GMT
> I'm always using integer instead of longs unless I'm not sure interger will
> be sufficient. This is one I wonder about in a 32 bit app.
I wonder about this too. I read something once about smaller variables being
less efficient, because their size gets increased so that they "align" in
memory with the larger ones.
?

Signature
Brian Schwartz
FishNet Components
http://www.fishnetcomponents.com
Building better tools for developers - Be part of it!
Ralph - 30 Dec 2004 22:19 GMT
> I've been obsessed lately with performance tweaks.
>
[quoted text clipped - 64 lines]
> object not to mention having extra 'item' fields available. Anyone played
> with this and checked performance?
If you are really into performance then first, you must obtain a copy of
Matt Currland's book "Advance Visual Basic 6". Also read Bruce McKinney's
"Hardcore Visual Basic" which is included on the MSDN Library/Help CD.
[Sidenote: M$ includes the Ver 2 book, but the sample code is for vb5 - you
can download the updated code at:
http://brucem.mystarband.net/mckinney2a.htm
The most important aspect of learning how to generate better performance is
profiling and testing your code. As an application becomes more complex it
is often not possible to predict actual behavior within YOUR problem domain.
Both of the above books not show methods of optimizing code, but ways to
measure their effect as well.
I would also recommend checking out the vbAccelerator site:
http://www.vbaccelerator.com
(Also the various vb mvp's sites)
Functions and Subs -
Yes, for some return types there is additional code created for providing a
return that presents an "over-head" if it is not used. In other situations
it is essentially a none issue - again you have to test to make sure.
Part of the difficulty with this type of "thought-tuning" is that compiling
a VB application is a multiple step process. One of these steps, if
compiling to native code, is the optimizer. Often rather lengthy, wasteful
appearing code is optimized down to something rather slick (the opposite can
happen just as easily <g>). In some cases compiling to "pcode" will result
in a faster operation than native code. Again you have to test.
Integers and Longs -
In most languages an 'integer' is the common integral type for the the
platform. eg, in Win32 it is 32-bit. In VB6 an Integer is a 16-bit creature,
a Long is 32-bit. In general, operations are faster in Win32 using a VB Long
and not a VB Integer. But again, in practice, you will have to test it as
you can run into another of VB's little idiosyncrasies: VB's hidden type
coercion. VB might in some cases convert longs to integers and vice versa.
Often little difference is actually noted in practice by this apparently
obvious performance issue.
Static Variables -
A static variable is simply a 'global' variable that can only be seen in the
scope of the routine it is defined in. An auto variable is one that is setup
on the stack when a function is called. So yes you can save a few clicks
when a routine is called repeatedly. The trade-off is your code image
becomes larger. Also if the 'static variable' is used like an auto and has
to be set to some intial value each time the routine is called - you have
lost some of the clicks you thought you were saving.
It is also possible that you might limit the optimizer from creating its
best output by using this technique opposed to using stack variables.
Again - you have to test and see.
With...End With -
Because of VB's 'interpreted' roots and its 'COM' model when using objects
(a horrible generalization <g>), using With...End With is always a good
idea. But it is only useful when a particular multi-level reference is
'referenced' more than one time. eg, your second example is essentially what
the With...End With construct does.
Again try it and see with your components in your problem domain.
Dictionary Object -
The dictionary object is one of the few cases where something in the FSO can
actually be faster than VB6's inherent Collection. But using anything from
the FSO is potentially a problem and VB's Collection class is poorly
written.
There are various alternative "collection" classes available on the net. Use
one of them.
Whew! hth
-ralph
Ralph - 30 Dec 2004 22:59 GMT
Erratum:
s/the above books not show methods of optimizing code/the above books not
only do show methods of optimizing code/g
-ralph
J French - 31 Dec 2004 12:16 GMT
I'll tag onto Ralph's post
- most of which I agree with 100%
In addition:
Never write Functions that return an untyped variable
- they are really returning a Variant
- and that Deviant (sic) is actually a hidden parameter on the stack
- and just don't ask what it points to ....
Use of Static is fine if what you are doing is 'charging up' a
Function/Sub so that it does not need to do daft Setup work the next
time round
- basically if you are replacing the old 'DATA' statement that has
gone AWOL in V versions of VB
Mostly 'trimming' will not make code faster, unless you have a routine
that is called 1000 times per second, or a /huge/ routine that ...
well just should not be there
(Ok - I know, it just growed .. and it makes sense .. but despite all
those excuses, I've always found that nicely compartmentalized code
runs faster - and even better .. it keeps running)
Mostly speed improvements are down to improving /algorithms/ not
resorting to APIs or doing /unsubtle/ caching.
Oddly, clean and easily understandable code normally runs faster than
something that is a bit 'obscure'
Also, as Ralph did not exactly point out
- on a well run machine the FSO will simply not exist