Board index » delphi » Optimization issues (esp. copying arrays)

Optimization issues (esp. copying arrays)

Hi there,
As part of the script interpreter for ViRC '96, I have a routine which
needs to execute a number of script statements, and maintains a
parameter array (PVars). This array must be kept constant between loops
in the function, however, parts of the function do change the array. So,
at the beginning of the function, I have this. Both PVars and PVarsOld
are declared as array[0..9, 0..1] of string.

    for j := 0 to 9 do
    begin
      PVarsOld[j, 0] := PVars[j, 0];
      PVarsOld[j, 1] := PVars[j, 1];
    end;

At the beginning of each new loop in the function, I have this:

    for j := 0 to 9 do
    begin
      PVars[j, 0] := PVarsOld[j, 0];
      PVars[j, 1] := PVarsOld[j, 1];
    end;

This works, however, performance for this function is absolutely
critical and these two fragments take up about 20% of the total
execution time of the function. I really need a way of getting this
down. The compiler doesn't like PVars := PVarsOld (not surprising;
however, I get an "incompatible types" error - what?!?), and I can't do
Move(PVars, PVarsOld, sizeof(PVars)), because that simply copies the
pointers and not the strings. Any ideas how I can optimize this code?

Also, one other thing: I notice that Delphi has the keyword inline
reserved - however, I've tried appending this to function declarations
and the compiler complains, so obviously it isn't implemented yet. Why
not? Surely it's not difficult to include support for inline functions
in the compiler, and the performance gains on small routines can be
SUBSTANTIAL. What gives? Will we see this in Delphi 3?

Finally, I've been getting periodic strange errors in some of the larger
modules in my project (esp. the two that are over 8000 lines long each).
That is, sometimes after adding some new chunks of code, the compiler
complains with a "Line longer than 255 characters" error. What? First
off, none of my lines are longer than 255 characters, and secondly, the
D2 compiler supposedly supports lines up to 32k in length anyway (and it
does; I've tested this). So the error is obviously misplaced ... the
only solution is to delete 10 or 15 comment lines and then it compiles
OK, until the next time .. well, sooner or later I'll run out of comment
lines to delete and then I'll be stuck!! Obviously I'm coming up against
some sort of compiler limit (or at least the compiler mistakenly thinks
I have) ... but 8000 lines? What? If there is a limit, WTF is it set so
low? Has anyone else experienced this and got a better solution?

Thanks, cheers,
+-----------------------------+------------------------------------+
| Adrian Cable [Doom Master!] | Internet: [MeGALiTH on IRC]        |
| Fidonet: 2:252/169.3        | aca...@sv.span.com                 |
+-----------------------------+------------------------------------+
| Latest ViRC '96 release: 0.61                                    |
| Get it from: http://apollo3.com/~acable/virc.html                |
+------------------------------------------------------------------+

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: 2.6.3i

mQBNAzICpWsAAAECAKELh2Zi1a+jD1Nj7VYloLg+uVimsRZHv5DgfCDOOo0nnXNq
KE19vjB1ZD4Rs1NTP8cQEjsnTwrHajgcZK8ecUkABRG0IUFkcmlhbiBDYWJsZSA8
YWNhYmxlQHN2LnNwYW4uY29tPokAVQMFEDICpWtqOBxkrx5xSQEBYjkB/jEcpWFp
y4t6XKL/zj34hfyCZYJKXQpuJlMWklywhu5OC2Z6WlsKeS6deKTyrW0GWw9hw6gS
qPdw+TcN9PSQBbE=
=6ioa
-----END PGP PUBLIC KEY BLOCK-----

 

Re:Optimization issues (esp. copying arrays)


On Mon, 30 Sep 1996 19:04:24 +0100, Adrian Cable
<megal...@jimc.demon.co.uk> you smacked the keyboard repeatedly to
write:

[Snip]

Quote

>    for j := 0 to 9 do
>    begin
>      PVarsOld[j, 0] := PVars[j, 0];
>      PVarsOld[j, 1] := PVars[j, 1];
>    end;

>At the beginning of each new loop in the function, I have this:

>    for j := 0 to 9 do
>    begin
>      PVars[j, 0] := PVarsOld[j, 0];
>      PVars[j, 1] := PVarsOld[j, 1];
>    end;

Delphi's Optimizer may already do this, but you could unroll the
loops, this will save 9 increments and possibly some offset
calculations if the compiler does this before hand (which it probably
does).

      PVars[0, 0] := PVarsOld[0, 0];
      PVars[0, 1] := PVarsOld[0, 1];
      PVars[1, 0] := PVarsOld[1, 0];
      PVars[1, 1] := PVarsOld[1, 1];
      PVars[2, 0] := PVarsOld[2, 0];
      PVars[2, 1] := PVarsOld[2, 1];
      PVars[3, 0] := PVarsOld[3, 0];
      PVars[3, 1] := PVarsOld[3, 1];
      PVars[4, 0] := PVarsOld[4, 0];
      PVars[4, 1] := PVarsOld[4, 1];
      PVars[5, 0] := PVarsOld[5, 0];
      PVars[5, 1] := PVarsOld[5, 1];
      ..
        ..
      PVars[9, 0] := PVarsOld[9, 0];
      PVars[9, 1] := PVarsOld[9, 1];

Quote
>This works, however, performance for this function is absolutely
>critical and these two fragments take up about 20% of the total
>execution time of the function. I really need a way of getting this

Have you run you code through a profiler to determine this? Or do you
have any code to time this?  I would hate to see you optimise this
part of the code if its really only 2% and something else was 18% of
the problem.

Quote
>down. The compiler doesn't like PVars := PVarsOld (not surprising;
>however, I get an "incompatible types" error - what?!?), and I can't do
>Move(PVars, PVarsOld, sizeof(PVars)), because that simply copies the
>pointers and not the strings. Any ideas how I can optimize this code?

Use PChars so that you just copy the POINTER to the string and not the
string itself.

Quote
>Also, one other thing: I notice that Delphi has the keyword inline
>reserved - however, I've tried appending this to function declarations
>and the compiler complains, so obviously it isn't implemented yet. Why
>not? Surely it's not difficult to include support for inline functions
>in the compiler, and the performance gains on small routines can be
>SUBSTANTIAL. What gives? Will we see this in Delphi 3?

Its there, the compiler just controls that.  I saw a message that
talked about the $G compiler directive that would allow you to group
functions and the such in the same code segment, you might want to
look at that.

Quote

>Finally, I've been getting periodic strange errors in some of the larger
>modules in my project (esp. the two that are over 8000 lines long each).
>That is, sometimes after adding some new chunks of code, the compiler
>complains with a "Line longer than 255 characters" error. What? First
>off, none of my lines are longer than 255 characters, and secondly, the
>D2 compiler supposedly supports lines up to 32k in length anyway (and it
>does; I've tested this). So the error is obviously misplaced ... the
>only solution is to delete 10 or 15 comment lines and then it compiles
>OK, until the next time .. well, sooner or later I'll run out of comment
>lines to delete and then I'll be stuck!! Obviously I'm coming up against
>some sort of compiler limit (or at least the compiler mistakenly thinks
>I have) ... but 8000 lines? What? If there is a limit, WTF is it set so
>low? Has anyone else experienced this and got a better solution?

I have, it happens when I copy source from the MAC to the PC, the MAC
terminates the end-of-line differently then the PC, and the Editor
does not like it.   I use a different editor that strips the extra
characters out and I no longer have any problems.  I use Q-Edit if in
DOS, or MultiEdit 7.x if in Windows.

The best optimization you can do is to look at HOW and WHY you are
doing certain things, then look for different ways of doing the same
thing.  The best optimization comes from changing the way you do
things rather than doing hand optimization of code segments.  It is
extreamly important that you have benchmarks of the program, and the
code in question.  Without these, you wont have any idea of what
effect you really had on the code.

A book that I highly recommend is "Zen of Code Optimization" by
Michael Abrash ISBN 1-883577-03-9.  Its heavy on the assembler side
(80x86), but it has a lot of excellent information concerning
optimization in general.

Brien King
bk...@primenet.com

Re:Optimization issues (esp. copying arrays)


Quote
In article <32500BA8.5...@jimc.demon.co.uk> Adrian Cable <megal...@jimc.demon.co.uk> writes:
>From: Adrian Cable <megal...@jimc.demon.co.uk>
>Subject: Optimization issues (esp. copying arrays)
>Date: Mon, 30 Sep 1996 19:04:24 +0100
>Hi there,
>As part of the script interpreter for ViRC '96, I have a routine which
>needs to execute a number of script statements, and maintains a
>parameter array (PVars). This array must be kept constant between loops
>in the function, however, parts of the function do change the array. So,
>at the beginning of the function, I have this. Both PVars and PVarsOld
>are declared as array[0..9, 0..1] of string.
>    for j := 0 to 9 do
>    begin
>      PVarsOld[j, 0] := PVars[j, 0];
>      PVarsOld[j, 1] := PVars[j, 1];
>    end;
>At the beginning of each new loop in the function, I have this:
>    for j := 0 to 9 do
>    begin
>      PVars[j, 0] := PVarsOld[j, 0];
>      PVars[j, 1] := PVarsOld[j, 1];
>    end;
>This works, however, performance for this function is absolutely
>critical and these two fragments take up about 20% of the total
>execution time of the function. I really need a way of getting this
>down. The compiler doesn't like PVars := PVarsOld (not surprising;
>however, I get an "incompatible types" error - what?!?), and I can't do
>Move(PVars, PVarsOld, sizeof(PVars)), because that simply copies the
>pointers and not the strings. Any ideas how I can optimize this code?

How about

Move(PVars^, PVarsOld^, sizeof(PVars^))

<snip>

HTH

Boris Ingram, Cyborg Software
boris...@iafrica.com
100076.3...@compuserve.com
http://www.pcb.co.za/users/borising/cyborg.htm

Re:Optimization issues (esp. copying arrays)


Quote
Adrian Cable wrote:
> [snip]
> Both PVars and PVarsOld are declared as array[0..9, 0..1] of string.[snip]
> The compiler doesn't like PVars := PVarsOld (not surprising;
> however, I get an "incompatible types" error - what?!?),

Assuming you have:
var
  PVars    : array[0..9, 0..1] of string;
  PVarsOld : array[0..9, 0..1] of string;

the type of PVars is actually different from PVarsOld. This is how
Pascal works. The reason is that Pascal being strongly typed, needs
a type for everything, so it will create a type for you. In your
example, it'll create two types. (This is actually a good thing.)  
To make PVars and PVarsOld the same type, you'll need to define a
named type for the array:

type
  TParameterType = array[0..9, 0..1] of string;
var
  PVars    : TParameterType;
  PVarsOld : TParameterType;

If you're using Delphi 2, the assignment PVars := PVarsOld will only
copy the pointers to the strings. The actual strings will only be
copied when you modify them. If you're using Delphi 1, an obvoius
optimization would be to shorten the length of the strings so you
only copy say 100 bytes pr. string instead of 256.

M.

--
Martin Larsson, author of several unknown utilities for DOS and Windows.
mailto:martin.lars...@delfi-data.msmail.telemax.no
http://www.delfidata.no/users/~martin
X.400:G=martin;S=larsson;O=delfi-data;P=msmail;A=telemax;C=no

Re:Optimization issues (esp. copying arrays)


Quote
Adrian Cable wrote:

> As part of the script interpreter for ViRC '96, I have a routine which
> needs to execute a number of script statements, and maintains a
> parameter array (PVars). This array must be kept constant between loops
> in the function, however, parts of the function do change the array. So,
> at the beginning of the function, I have this. Both PVars and PVarsOld
> are declared as array[0..9, 0..1] of string.

>     for j := 0 to 9 do
>     begin
>       PVarsOld[j, 0] := PVars[j, 0];
>       PVarsOld[j, 1] := PVars[j, 1];
>     end;

> At the beginning of each new loop in the function, I have this:

>     for j := 0 to 9 do
>     begin
>       PVars[j, 0] := PVarsOld[j, 0];
>       PVars[j, 1] := PVarsOld[j, 1];
>     end;

> This works, however, performance for this function is absolutely
> critical and these two fragments take up about 20% of the total
> execution time of the function. I really need a way of getting this
> down. The compiler doesn't like PVars := PVarsOld (not surprising;
> however, I get an "incompatible types" error - what?!?), and I can't do
> Move(PVars, PVarsOld, sizeof(PVars)), because that simply copies the
> pointers and not the strings. Any ideas how I can optimize this code?

As Martin Larsson has pointed out, the incompatible type error almost
certainly is because you declared something like
  var
    PVars:    array[0..9, 0..1] of string;
    PVarsOld: array[0..9, 0..1] of string;
If you declare
  type
    TVarArray = array[0..9, 0..1] of string;
  var
    PVars, PVarsOld: TVarArray;
you should be able to do "PVarsOld := PVars" and vice versa. However, you
may not see a huge speed improvement here, because D2 strings are
reference counted. While "PVarsOld := PVars" is smaller and clearer than
your for loop, the compiler may actually generate very similar code, as it
will not just copy the string pointers but will also have to go through
and adjust each reference count.

If you don't need huge strings, you will probably see a big speedup by
using
  type
    TVarArray = array[0..9, 0..1] of string[255];
as then "PVarsOld := PVars" will just generate an inline Move().

Quote
> Also, one other thing: I notice that Delphi has the keyword inline
> reserved - however, I've tried appending this to function declarations
> and the compiler complains, so obviously it isn't implemented yet. Why
> not? Surely it's not difficult to include support for inline functions
> in the compiler, and the performance gains on small routines can be
> SUBSTANTIAL. What gives? Will we see this in Delphi 3?

Inline disappeared in D2. I'd bet against its coming back in D3, at least
in the horrible old hexadecimal way - I get the impression that Borland is
at least thinking about porting Delphi to other CPU's. True inline BASM
macros would be nice, but people have been asking for those for years ....

Quote
> Finally, I've been getting periodic strange errors in some of the larger
> modules in my project (esp. the two that are over 8000 lines long each).
> That is, sometimes after adding some new chunks of code, the compiler
> complains with a "Line longer than 255 characters" error. What? First
> off, none of my lines are longer than 255 characters, and secondly, the
> D2 compiler supposedly supports lines up to 32k in length anyway (and it
> does; I've tested this). So the error is obviously misplaced ... the
> only solution is to delete 10 or 15 comment lines and then it compiles
> OK, until the next time .. well, sooner or later I'll run out of comment
> lines to delete and then I'll be stuck!! Obviously I'm coming up against
> some sort of compiler limit (or at least the compiler mistakenly thinks
> I have) ... but 8000 lines? What? If there is a limit, WTF is it set so
> low? Has anyone else experienced this and got a better solution?

Current project is over 110,000 lines, and we've seen some rather strange
error messages. Delphi's error reporting definitely seems to get confused
on large projects. It's rather worrisome, but so far we haven't seen any
instances of misgenerated code.

What I would ask you is why do you have 8000 line units? That's a huge
chunk of code - surely it doesn't really all belong together?

--

http://www.midnightbeach.com/jon   Personal Pages
http://www.midnightbeach.com/jon/pubs Programming Publications
http://www.midnightbeach.com/hs             Home School Resource List

Other Threads