Examples Delphi

Performance Tips and Tricks
A good Design is much more important to how fast
your application will execute.
So my suggestion is:
Switch optimization on and make sure your app is
well designed. Then you'll probably have an application
that is fast enough.
**********************
Checkout:
http://www.optimalcode.com/
Regards,
Anthony Richardson
anthony_r@sageautomation.com
**********************
another tip is to minimise memory reallocations... EG reversing a string.
function ReverseString (const Source :String):String;
var
I :Integer;
begin
Result := '';
for I := Length(Source) downto 1 do Result := Result + Source[I];
end;
or alternatively
function ReverseString (const Source :String):String;
var
I,SLen :Integer;
begin
SetLength(Result,Length(Source));
SLen := 1;
for I := Length(Source) downto 1 do begin
Result[SLen] := Source[I];
inc(SLen);
end;
end;
no reallocations in the second as the length of Result is set once.
**********************
While loops evaluate their end condition every iteration which will incur extra
overhead in return for more powerful semantics.
**********************
Optimising:
1: In most cases one hour of your time is worth more than 1000
hours of computer time. There is almost never a benefit in having
the worlds fastest dialog box or smallest file loader.
2: Buy component sets (with source code) and save yourself a bundle.
$100 of your time is what, 2-3 hours? It gets you the TurboPower
basic utilities (string handling, dialogs etc) as one example.
Or spend the time surfing the Delphi Super page and Torrys. Why
reinvent the wheel?
3: Unless you profile it's very difficult to know where hand
optimisation will give you a benefit.
4: The easiest hand optimisation I know of is religous use of
parameter passing mechanisms. If at all possible make parameters
const. Put integer and pointer parameters first in the list as
they are eligable for being put in registers, and only the first
three can have registers (in i86 machines anyway). Be aware of
what you're passing (how bit it is, whether it's needed at all)
5: work on speeding up (reducing the use of) slow things first.
Database access, file access and graphics in that order. It can
be worth using a sorted TList and hash or binary search if you
search things a lot.
6: put data in memory if speed is an issue. Trading memory for
speed is often cheap and easy to code.
Paul Jackson wrote:
> 1) when passing parameters, use var, const or out as required
> can speed up code, the use of the out parameter is more efficient
More so in Pascal than Delphi AFAIK. Delphi has overheads that make
this a minor point. Doubly indirect method calls sprint to mind,
as well as the whole object model bundle.
> 2) The string handling functions you get with Delphi are inefficient
> 3) Use a profiler
USE A PROFILER! I'll say that again: the cheapest code is the code that
is never written, followed by code that is never executed. Optimising
either type of code is a complete waste of effort. Better to come up
with a good algorithm or design than an optimised bubble sort, I think.
Example:
I did a data transplation/import exercise transforming a couple of
100MB text files (fixed-width column records) into a 200+MB file using
about 5 other files (30MB total) as secondary tables. Putting the
secondary data in memory (TStringList.LoadFromFile) sped things up a
lot. Profiling showed that about 90% of the time was spent finding
keys in the secondary files. Since those files were sorted by primary
key I made a TStringList descendent with a binary search in it. Then I
put the keys into the list.Objects[] array as integers. That sped
things up by about another 100x. In all I spent two days coding
and about 2 hours executing. The first version (in memory, no binary
search) looked like taking 48+ hours but took about 8 hours to code.
Another 4 hours coding meant it took 1 hour to run, which turned out
to be good because I also found data inconsistencies which meant
regenerating the data files and re-running.
The point is that a tiny amount of profiling and re-design made a huge
difference, but no amount of optimised file handling could have given
more than probably a 10% speed increase.
Moz
**********************
Use AnsiCompareText(str1, str2 ) = 0 as opposed to UpperCase(str1) =
UpperCase(str2)
This a significant difference in performance. The uppercasing allocates new
string memory as well as the processing involved to traverse each string
once before the comparison even occurs.
**********************
One I have seen often is people not understanding the purpose of -1 being
returned from IndexOf methods. The rule should always be compare with
zero. The statement
to check if an Item was not in a list should be:
if List.IndexOf(Item)<0 then ...
not
if List.IndexOf(Item)=-1 then ...
the same applies to comparison methods that return -1, 0, 1 - use
comparisons with <0, =0 >0.
**********************
These are nice tips, but pardon me if I must add that they only apply to
your large Delphi projects on the ObjectPascal language level. And when
you want/need the best efficiency, you need more than that. My paper on
Delphi Efficiency (which started out as book on Borland Pascal
efficiency, see
http://www.drbob42.com/books/perform.htm)
outlines a number of levels you can apply performance optimisation. Usually,
this starts when your application is already slow and/or showing a
performance problem. The first step then is: find the bottle-neck
(really, only spend your efforts on that spot!). Step two is: check the
algorithms and data structures (again, only on the places that are the
bottle-necks). Step 3 is the first time you step down to the
ObjectPascal feature coding level, but you *only* apply this step if
step 2 failed or did not result in the required performance gain.
However, while some of your tips may result in a somewhat better
performance, a better algorithm (from O(N**2) to O(N log N) for example)
can lead to an incredible performance enhancement - making the
difference between a too-slow-to-use app and a useful app.
And that's not even the last step, as you can read in my paper (which is
almost an annual returning session at the Borland Conference, and of
which one of the latest editions is available on my website at
http://www.drbob42.com/delphi/perform.htm
Groetjes,
Bob Swart (aka Dr.Bob - www.drbob42.com)
**********************
I think many of these would be handled by the optimiser anyway, but all too
often, the optimiser screws up, and the only way to get your program to do
what you tell it is to turn it off (this is my default setting for
optimisation, and the first thing I check when I hit unexpected problems :)
There are many simple ways (which I am sure you know about, but many others
dont)....
Here are some of my own:
1) when passing parameters, use var, const or out as required can speed up
code, the use of the out parameter (according to a comment I recently found
in the VCL) is more efficient that defining a function that does the same
job. Each one has it's own benefit and drawbacks, so check the helpfile,
but basically they beat standard params by not having to recreate the values
for use in the target method...
2) The canned string handling functions you get with Delphi are VERY
inefficient, and it is always worth checking out other implementations of
the likes of Pos and copy from the net...
3) Use a profiler, there are many about, and can give you an idea what areas
of your code is underperforming, and where your time would be best spent for
the best time spent/results gained ratio...
As for Davids suggestions:
1) Pred is an optimised method for subtracting 1 from a number, electronic
processors are very bad at subtracting (thinking back to my university days,
they have to jump though some serious hoops, to get the result, nines
compliment and all that, where by Pred only needs to perform a simple
bitwise operation)
2) Length(str)... Delphi stores a numeric value alongside every string
allocated that determines the length of the string (check out "absolute" in
the help file), this is the value Length returns, so I would imagine this is
also quicker...
3) Counting down a for loop is more effiecient, that counting up (this is
definately done by optimisation (badly)...
4) I imagine AnsiCompareText is quicker for long strings (converting each of
those strings to uppercase is expensive if the first characters don't
match... you need not have bothered converting the rest :)
5) Is number 5 quicker? I know the theory of the compiler having to create
extra code to handle else's and that this is quicker, but I can see not
benefit here....
I would agree with David that the optimiser is really bad...and as a rule, I
always have it turned off...Does anyone know if there is a list of
everything the optimiser is supposed to do?
There is also a point where neat, understandable code can become more
important than optimisation, so the few David are worth bearing in mind
because they are still easy to read when used in code....
**********************
Use AnsiCompareText(str1, str2 ) = 0 as opposed to UpperCase(str1) =
UpperCase(str2)
Well, that is a good one. I forget about AnsiCompareText sooo often....
**********************
> > 3. Use AnsiCompareText(str1, str2 ) = 0 as opposed to UpperCase(str1) =
> > UpperCase(str2)
>
>This a significant difference in performance. The uppercasing allocates new
>string memory as well as the processing involved to traverse each string
>once before the comparison even occurs.
Absolutely; in a tight loop doing a lot of compares, all those UpperCases
can add a huge amount of time.
A small nitpick: AnsiCompareText does not perform the same case mapping as
LowerCase and UpperCase; use "CompareText" if you want the equivalent
equality test to using UpperCase.