_OPTI Optimization Report

Top  Previous  Next

 

[BP7,D1,D2,D3,D4,D5,D6,D7,D8, D2005W, D2005N, D2006W, D2006N, D2007W, D2009W, D2010W, DXEW]

 

This report pinpoints elements of the code that you can improve, resulting in better performance. With better performance, we here mean faster execution, not necessarily smaller code.

 

__________________________________________________

 

Missing “const” for unmodified string parameter

 

[BP7,D1,D2,D3,D4,D5,D6,D7,D8, D2005W, D2005N, D2006W, D2006N, D2007W, D2009W, D2010W, DXEW]

This is a list of all string parameters that you can declare with the const directive, resulting in better performance since the compiler can assume that the parameter will not be changed. For example, for a long string the reference count for the string does not need to be updated on entry and exit to the function. For other types of strings, like WideString, the string may have to be copied when passed to the function.

 

Example:

 

procedure MyProc(S : string);

begin

..

if S = 'Foo' then // !! S is not changed

begin

..

end;

..

end;

 

In this case, the parameter S should have the const directive, since it is never changed in the procedure. The compiler can generate code that is more efficient.

 

No warning is given for methods that are marked with the "override" directive. This is because they must follow the parameter list that the overridden method has.

 

__________________________________________________

 

Missing “const” for unmodified record parameter

 

[BP7,D1,D2,D3,D4,D5,D6,D7,D8, D2005W, D2005N, D2006W, D2006N, D2007W, D2009W, D2010W, DXEW]

This is a list of all record parameters that you can declare with the const directive, resulting in better performance since the compiler can assume that the parameter will not be changed. Generally, if the parameter is larger than 4 bytes, and it doesn't need to be altered in the subroutine, const is more efficient. Also, it is a good idea to use CONST on parameters that aren't intended to be altered, so the compiler can catch those errors for you.

 

Example:

 

type

TRec = record

X : integer;

end;

 

procedure MyProc(R : TRec);

begin

..

if R.X = 5 then // !! R is not changed

begin

..

end;

..

end;

 

In this case, the parameter R should have the const directive, since it is never changed in the procedure. The compiler can generate code that is more efficient.

 

No warning is given for methods that are marked with the "override" directive. This is because they must follow the parameter list that the overridden method has.

 

__________________________________________________

 

 

Missing "const" for unmodified array parameter

 

[BP7,D1,D2,D3,D4,D5,D6,D7,D8, D2005W, D2005N, D2006W, D2006N, D2007W, D2009W, D2010W, DXEW]

This is a list of all array parameters that you can declare with the const directive, resulting in better performance since the compiler can assume that the parameter will not be changed.

 

No warning is given for methods that are marked with the "override" directive. This is because they must follow the parameter list that the overridden method has.

 

__________________________________________________

 

 

Array properties that are referenced/set within methods

 

[D1,D2,D3,D4,D5,D6,D7,D8, D2005W, D2005N, D2006W, D2006N, D2007W, D2009W, D2010W, DXEW]

This is a list of all array properties that are referenced or set within methods of a class. Methods that include a reference to the property are listed.

 

For performance reasons it is faster to directly access the private array field. However, if the Get- or Set-method performs side effects, it makes sense to access the property.

 

For simple non-array properties, the compiler generates the same code for both access of the property or the field. Therefore, for normal properties there is no advantage in referencing the private field.

 

Example:

 

type

TMyClass = class

private

FItems : array[0..10] of integer;

FPlain : integer;

protected

function GetItem(Index : integer) : integer;

procedure SetItem(Index, Value : integer);

public

property Items[Index : integer] : integer read GetItem write SetItem;

property Plain : integer read FPlain write FPlain;

procedure MyProc;

end;

 

function TMyClass.GetItem(Index : integer) : integer;

begin

Result := FItems[Index];

end;

 

procedure TMyClass.SetItem(Index, Value : integer);

begin

FItems[Index] := Value;

end;

 

procedure TMyClass.MyProc;

begin

if Items[0] < 5 then  //!! ineffective, calls GetItem

Items[0] := 5;      //!! ineffective, calls SetItem

 

if FItems[0] < 5 then //!! this is faster

FItems[0] := 5;

 

Plain := 5;  // these two lines generate the same machine code

FPlain := 5;

end;

 

__________________________________________________

 

 

Virtual methods (procedures/functions) that are not overridden

 

This is a list of all methods that are declared as virtual, but that never are overridden. Since virtual methods have slightly worse performance than static methods, it is better to change these methods to static ones instead.

 

This section is also generated for multi-projects.

 

Recommendation:

 

Examine if these methods should really be overridden. If they belong to a base class, they should probably remain virtual, so descendant classes can create their own implementations.

 

 

__________________________________________________

 

 

Local subprograms with references to outer local variables

 

This section shows nestled local procedures, with references to outer local variables. Those local variables require some special stack manipulation so that the variables of the outer routine can be seen by the inner routine. This results in a good bit of overhead.

 

 

See also:

 

R_GEN General Reports