Avoiding implicit try finally section

From Free Pascal wiki
Revision as of 20:12, 29 December 2004 by Michalis (talk | contribs) (Corrected italics, better wording)
Jump to navigationJump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Note: On 2004-12-26 Peter Vreman fixed this in compiler. This means that starting from FPC 1.9.5 2004-12-26, information on this page is no longer relevant. With newer compiler timings of demo program on this page show no significant difference between Test_ResourceString and Test_ResourceString_Fast.

If you know of any other case where implicit try...finally section may be created and significantly affect speed of some code, please update this page. Otherwise, just ignore this page if you're using FPC newer than 1.9.5 from 2004-12-26.

Sometimes it's important to know that compiler can wrap some code in implicit try ... finally section. In some cases this can significantly affect the speed of given code.

Here's a link to archived discussion on fpc-devel list regarding this issue, with subject "TList slowness in classes" : http://www.mail-archive.com/fpc-devel@lists.freepascal.org/msg01367.html

And below is a small demo program that

  • Shows a trick how to avoid implicit try ... finally block (without changing the meaning or safety of the code) in some cases.
  • When run, this program clearly shows that avoiding an implicit try ... finally block can make code a lot faster. When I run this program on my system, I get
Time of Test_ResourceString:        107
Time of Test_ResourceString_Faster: 16
{$mode objfpc}

uses
  {BaseUnix, Unix needed only to implement Clock} BaseUnix, Unix,
  SysUtils;

function Clock: Int64;
var Dummy: tms;
begin
 Clock := FpTimes(Dummy);
end;

resourcestring
  SResString = 'blah blah blah blah blah blah blah blah blah blah';

{ Note that Test_ResourceString and Test_ResourceString_Fast 
  do exactly the same thing. }

procedure Test_ResourceString(i: Integer);
begin
 if i = -1 then raise Exception.Create(SResString);
end;

procedure Test_ResourceString_Faster(i: Integer);

  procedure RaiseError;
  begin
   raise Exception.Create(SResString)
  end;

begin
 if i = -1 then RaiseError;
end;

{ Note that when I call Test_ResourceString and Test_ResourceString_Fast
  i is always >= 0 so Exception is never actually raised. }

const
  TestCount = 10000000;
var
  i: Integer;
  Start: Int64;
begin
 Start := Clock;
 for i := 0 to TestCount do Test_ResourceString(i);
 Writeln('Time of Test_ResourceString:        ', Clock - Start);
 
 Start := Clock;
 for i := 0 to TestCount do Test_ResourceString_Faster(i);
 Writeln('Time of Test_ResourceString_Faster: ', Clock - Start);
end.