Code/Rom Size, Ram Size and Speed tips.



See also
Janni's website
Janni's website


Content
Code/Rom Size tips
Ram Size tips.
Execution speed tips


Code/Rom Size tips

Use nested Ifs in stead of long expressions with AND.

Tip from joseLB.
   IF (expression1) AND (expression2)...
is much bigger than
   IF expression1 then
     IF expression2 then ....

In while loops (or repeat loops) it is better to change this
  while (expression1) AND (expression2)... do // e.g. while (VarA > VarB) and (VarC < 4) do
  begin
    ...
  end;
into this:
  while true do
  begin
    if (not expression1) then break; // e.g. if (VarA <= VarB) then break;
    if (not expression2) then break; // e.g. if (VarC >= 4) then break;
    ...
  end;

Use while loops in stead of For loops.

Tip from joseLB.
   FOR k := 1 to y do
   begin
     ...
   end;
is bigger than
   k := 1;
   while k <= y do
   begin
     ...
     k := k + 1;  // do not forget to increment the loop variable
   end;

Do not use complex function results.

Using var parameters for complex function results gives smaller code (and maybe smaller ram size) than making functions that return complex results. In the PRO version it is possible to make functions with complex results, e.g. strings.
However:
function Test: string[5];  // function returns complex result
begin
  Result := ...;
end;
...
MyString := Test;
costs a lot more code than
procedure Test(var S: string[5]); // procedure returns complex result via a var parameter
begin
  S := ...;
end;
...
Test(MyString);
The reason is a.o. an extra copying operation if the result is to be used (e.g. in "MyString := Test;") of the return value into the final destination. Also the function itself uses more code.
Additionally it can cost more Ram because an extra "Result" local variable of the result type has to be created. It it can be overlaid then there is of course no extra ram usage.
So, the "old" var parameter method is the cheapest.

Avoid large literal strings in the code.

Place the large literal strings into "constant" in stead of putting them in the code and either
- make your routines work (also) with constant strings as parameters (if possible), or
- copy (see example below) the rom strings to ram if a procedure or function requires a ram string as parameter.
Reason: filling e.g. a string variable with a literal value costs a lot of code, related to the size of the literal value.
// with usage of literal string in code:
  TestStr := '123456789012345678901234567890'; // costs 130 bytes of code (P18)

// with usage of string value in constant area:
const StringValue: string[30] = '123456789012345678901234567890'; // costs 31 bytes of rom
  ... 
  StrCpyC(TestStr, @StringValue); // costs 24 bytes in code
                                  // additionally there is a (one time only) overhead for StrCopyC (30 bytes).

Use the "with" statement when handling arrays of records.

See also here.

Without "with" usage:
procedure One;  // most rom size (364)
var I: byte;
begin
  for I := 0 to 19 do
  begin
    ArrayRec[I].S_ := 'test value';
    ArrayRec[I].A_ := 10;
    ArrayRec[I].B_ := 20;
    ArrayRec[I].C_ := 30;
    ArrayRec[I].D_ := 40;
    ArrayRec[I].E_ := 50;
    ArrayRec[I].F_ := 60;
  end;
end;

With "with" usage:
procedure One_with;  // average rom size (212) = 42% down
var I: byte;
begin
  for I := 0 to 19 do
  begin
    with ArrayRec[I] do
    begin
      S_ := 'test value';
      A_ := 10;
      B_ := 20;
      C_ := 30;
      D_ := 40;
      E_ := 50;
      F_ := 60;
    end;
  end;
end;

Using "pointers":
procedure One_Ptr;   // least rom size  (200) = 45% down
var Ptr: ^Trec;
    I : byte;
begin
  Ptr := @ArrayRec;

  for I := 0 to 19 do
  begin
    Ptr^.S_ := 'test value';
    Ptr^.A_ := 60;
    Ptr^.B_ := 50;
    Ptr^.C_ := 60;
    Ptr^.D_ := 30;
    Ptr^.E_ := 20;
    Ptr^.F_ := 10;

    inc(Ptr);
  end;
end;


Ram Size tips

Avoid literal string parameters.

The possibility is built in in mP to pass literal strings in stead of string variables as parameter to functions. e.g.
  TestFunction ('testText'); // Can take more ram than the next method, see below
in stead of
  MyString := 'testText';    // This method is to be preferred if you have "MyString" available already
  TestFunction (MyString);   // If you don't have a "Mystring" then both methods are equal in rom/ram usage.
Both methods are the same in codesize and ramsize, but if you have already a string variable available that you can use to take the content of the literal string (like in the second example above), it is better to use that one. It saves ram because, when using the first method, the compiler itself creates an extra string variable, fills it with the literal string, and passes it to then the function.

Avoid string concatenation with '+'.

When doing string concatenation with '+' and extra copy of the destination strings is created (name of the variable is preceded by "FLOC_" in the listing).
In some cases the extra variable can be overlaid, in other cases not.
var Strng: string[100];
...
Strng := Strng + 'abc'; // <------ here an extra string[100] variable is created
StrCat(Strng, 'abc');   // <------ and here it is not...


Execution Speed tips

none yet.
-------------------------------------------