Re: [fpc-devel] TList slowness in classes
> > Talking about TList slowness: > > In the last years TList and TStringList became slower and slower. > > Are there any alternatives in classes.pp? A simple TList providing only > > the very basics, less checks, no notifications, less virtuals, reordered > > IFs ... ? > > TList has almost no virtuals, so I doubt you will find anything to > change there. The notifications can be optimized, Dean Zobec wanted to > try this. This is as far as I'm concerned the biggest showstopper. unnecessary things have been added to TList to accomodate descendants (very bad OOP design decision IMHO), like the notification to be used in the only descendant, TObjectList, that transformed the Clear operation from an O(1) to an O(n) operation. Here is what Delphi designer Danny Thorpe says about TList in his book Delphi component design (1997): "You'll almost always wind up using a TList in a component, but you'll never create descendants of TList. TList is a worker drone, not a promiscuous ancestor class." Unfortunately the programmers of Delphi 5 seem not to have read his book :-) another explanation from Danny: "If you want to create a list of a particular kind of item and that list is used only in the private or protected sections of your component implementation, then just use a plain TList and typecast the list's raw pointers into the type you put into the list to begin with. If the list is exposed in the public interface of your component, typecasting is not an option. You cannot require a component user to typecast a list item appropriately in order to access it. You should create a simple wrapper class (derived from TObject, not TList) that exposes only the property and function equivalents of TList that you need and whose function and whose function return types and method parameter types match the type of data that the list contains. The wrapper class then contains a TList instance internally and uses that for actual storage." So TObjectList should have been designed as a wrapper around TList, with no need to add the notification mechanisms in TList. I've began writing a tutorial for fpcunit and have chosen this refactoring of TList and TObjectList as a subject of unit testing for my tutorial. Hope to finish it in the next two weeks. >> Are there >> any alternatives in classes.pp? A simple TList providing only the very >> basics, less checks, no notifications, less virtuals, reordered IFs ... ? >> If this TBaseList (or TSimpleList or TQuickList or THumbleList) would be >> the ancestor of TList, see above, composition is a better solution then inheritance in this case IMHO Ciao, Dean ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TList slowness in classes
Michalis Kamburelis wrote: I suspected that every type that needs to be initialized/finalized creates such try...finally block, Yes, it does. but didn't have time to check. But I checked it now. OK, page in wiki is changed, and demo program there is changed. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TList slowness in classes
Vincent Snijders wrote: Michalis Kamburelis wrote: Are there any other cases where this issue may be significant ? If no, I'll mark this wiki page clearly as "only for FPC earlier than 2004-12-28" (to-be-removed when 2.0 comes in), else I will update it. (Note: we can continue this talk on wiki page http://www.freepascal.org/wiki/index.php/Talk:Avoiding_implicit_try_finally_section already started by Vincent with that question) Thanks! I haven't tested it, but I have this hunch. Ansistrings (not constant) also require implicit try finally. If you use ansi strings only in a seldom used if-branch in a procedure, you could extract the procedure too, just like you did for the resource string. for example: If (i>0) then 'do something but not with ansistrings else writeln('Invalid value: '+IntToStr(i)); Regards, Vincent. I suspected that every type that needs to be initialized/finalized creates such try...finally block, but didn't have time to check. But I checked it now. OK, page in wiki is changed, and demo program there is changed. -- Michalis ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TList slowness in classes
Michalis Kamburelis wrote: Are there any other cases where this issue may be significant ? If no, I'll mark this wiki page clearly as "only for FPC earlier than 2004-12-28" (to-be-removed when 2.0 comes in), else I will update it. (Note: we can continue this talk on wiki page http://www.freepascal.org/wiki/index.php/Talk:Avoiding_implicit_try_finally_section already started by Vincent with that question) Thanks! I haven't tested it, but I have this hunch. Ansistrings (not constant) also require implicit try finally. If you use ansi strings only in a seldom used if-branch in a procedure, you could extract the procedure too, just like you did for the resource string. for example: If (i>0) then 'do something but not with ansistrings else writeln('Invalid value: '+IntToStr(i)); Regards, Vincent. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TList slowness in classes
Vincent Snijders wrote: Michalis Kamburelis wrote: I felt that results of this discussion are so important that I created a page in FPC wiki about it: http://www.freepascal.org/wiki/index.php/Avoiding_implicit_try_finally_section There's an URL to mail archives of this discussion, and a small demo program that shows trick proposed by Mattias how to avoid this implicit try...finally block. (I also created Writing_efficient_code page, that links between FPC page and Avoiding_implicit_try_finally_section page). Michalis. Did you try this with today compiler? I think Peter Vreman turned of implicit try finally for resource strings. Vincent. I just updated from CVS and rebuild FPC, and indeed, timings of my test program are now Time of Foo_ResourceString:18 Time of Foo_ResourceString_Faster: 16 So it's fixed in compiler. Great! Are there any other cases where this issue may be significant ? If no, I'll mark this wiki page clearly as "only for FPC earlier than 2004-12-28" (to-be-removed when 2.0 comes in), else I will update it. (Note: we can continue this talk on wiki page http://www.freepascal.org/wiki/index.php/Talk:Avoiding_implicit_try_finally_section already started by Vincent with that question) Thanks! -- Michalis ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TList slowness in classes
Vincent Snijders wrote: Michalis Kamburelis wrote: I felt that results of this discussion are so important that I created a page in FPC wiki about it: http://www.freepascal.org/wiki/index.php/Avoiding_implicit_try_finally_section There's an URL to mail archives of this discussion, and a small demo program that shows trick proposed by Mattias how to avoid this implicit try...finally block. (I also created Writing_efficient_code page, that links between FPC page and Avoiding_implicit_try_finally_section page). Michalis. Did you try this with today compiler? I think Peter Vreman turned of implicit try finally for resource strings. Vincent. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel I can confirm that since the new CVS version TList is much faster than before. Also it seems arrays got faster but I'm unsure as I deleted my old benchmarks. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TList slowness in classes
On Fri, 24 Dec 2004, Mattias Gaertner wrote: > On Fri, 24 Dec 2004 12:13:15 +0100 (W. Europe Standard Time) > Michael Van Canneyt <[EMAIL PROTECTED]> wrote: > > > On Fri, 24 Dec 2004, Mattias Gaertner wrote: > >[...] > > > And creates the implicit exception frame only in RaiseIndexError. > > > > I have changed the procedure. > > Talking about TList slowness: > In the last years TList and TStringList became slower and slower. > Are there any alternatives in classes.pp? A simple TList providing only the > very > basics, less checks, no notifications, less virtuals, reordered IFs ... ? TList has almost no virtuals, so I doubt you will find anything to change there. The notifications can be optimized, Dean Zobec wanted to try this. This is as far as I'm concerned the biggest showstopper. If you want to make an ancestor, make it TAbstractList. But to make this work, you'll need a virtual Get() method, which is more or less what you wanted to avoid in the first place. > If this TBaseList (or TSimpleList or TQuickList or THumbleList) would > be the ancestor of TList, existing code could easily be improved - the > user only needs to rename his TList to TBaseList. > Or maybe give this base thing the correct name. I never understood, > why Borland named it 'list'. AFAIK in computer science a list is a > linked chain of elements. While TList is an dynamic array with some methods. It is. I suspect that TList is also often used in the wrong way. The basic methods (get/set) are quite small and fast. Only the growing mechanism is slow. People should set the capacity before adding anything to the list. If you don't do this, then each N calls to add() will need to do a reallocation of the whole list... Michael. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TList slowness in classes
Michalis Kamburelis wrote: I felt that results of this discussion are so important that I created a page in FPC wiki about it: http://www.freepascal.org/wiki/index.php/Avoiding_implicit_try_finally_section There's an URL to mail archives of this discussion, and a small demo program that shows trick proposed by Mattias how to avoid this implicit try...finally block. (I also created Writing_efficient_code page, that links between FPC page and Avoiding_implicit_try_finally_section page). Michalis. Did you try this with today compiler? I think Peter Vreman turned of implicit try finally for resource strings. Vincent. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: Re: [fpc-devel] TList slowness in classes
> >Talking about TList slowness: >In the last years TList and TStringList became slower and slower. Are there >any alternatives in classes.pp? A simple TList providing only the very basics, >less checks, no notifications, less virtuals, reordered IFs ... ? I think dynamic arrays are just what you are looking for. var ii: array of integer; ss: array of string; yakov ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TList slowness in classes
I felt that results of this discussion are so important that I created a page in FPC wiki about it: http://www.freepascal.org/wiki/index.php/Avoiding_implicit_try_finally_section There's an URL to mail archives of this discussion, and a small demo program that shows trick proposed by Mattias how to avoid this implicit try...finally block. (I also created Writing_efficient_code page, that links between FPC page and Avoiding_implicit_try_finally_section page). Michalis. Michael Van Canneyt wrote: On Fri, 24 Dec 2004, Mattias Gaertner wrote: On Fri, 24 Dec 2004 11:49:10 +0100 (W. Europe Standard Time) Michael Van Canneyt <[EMAIL PROTECTED]> wrote: On Fri, 24 Dec 2004, Mattias Gaertner wrote: On Fri, 24 Dec 2004 10:56:24 +0100 (W. Europe Standard Time) Michael Van Canneyt <[EMAIL PROTECTED]> wrote: If the answer is yes, then maybe it's safe to compile parts of FPC sources in lists.inc (like TList.Get) inside {$IMPLICITEXCEPTIONS OFF} ? Why not put it into a sub proc: function TList.Get(Index: Integer): Pointer; procedure RaiseIndexError; begin Error(SListIndexError,Index); end; begin If (Index<0) or (Index>=FCount) then RaiseIndexError; Result:=FList^[Index]; end; The compiler detects that the sub can raise an exception. And creates the implicit exception frame only in RaiseIndexError. I have changed the procedure. Michael. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TList slowness in classes
On Fri, 24 Dec 2004 12:13:15 +0100 (W. Europe Standard Time) Michael Van Canneyt <[EMAIL PROTECTED]> wrote: > On Fri, 24 Dec 2004, Mattias Gaertner wrote: >[...] > > And creates the implicit exception frame only in RaiseIndexError. > > I have changed the procedure. Talking about TList slowness: In the last years TList and TStringList became slower and slower. Are there any alternatives in classes.pp? A simple TList providing only the very basics, less checks, no notifications, less virtuals, reordered IFs ... ? If this TBaseList (or TSimpleList or TQuickList or THumbleList) would be the ancestor of TList, existing code could easily be improved - the user only needs to rename his TList to TBaseList. Or maybe give this base thing the correct name. I never understood, why Borland named it 'list'. AFAIK in computer science a list is a linked chain of elements. While TList is an dynamic array with some methods. Mattias ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TList slowness in classes
On Fri, 24 Dec 2004, Mattias Gaertner wrote: > On Fri, 24 Dec 2004 11:49:10 +0100 (W. Europe Standard Time) > Michael Van Canneyt <[EMAIL PROTECTED]> wrote: > > > > > > > On Fri, 24 Dec 2004, Mattias Gaertner wrote: > > > > > On Fri, 24 Dec 2004 10:56:24 +0100 (W. Europe Standard Time) > > > Michael Van Canneyt <[EMAIL PROTECTED]> wrote: > > > > > > > > If the answer is yes, then maybe it's safe to compile parts of FPC > > > > > sources in lists.inc (like TList.Get) inside {$IMPLICITEXCEPTIONS > > > > > OFF} ? > > > > > > Why not put it into a sub proc: > > > > > > function TList.Get(Index: Integer): Pointer; > > > > > > procedure RaiseIndexError; > > > begin > > > Error(SListIndexError,Index); > > > end; > > > > > > begin > > > If (Index<0) or (Index>=FCount) then > > > RaiseIndexError; > > > Result:=FList^[Index]; > > > end; > > > > > > > The compiler detects that the sub can raise an exception. > > And creates the implicit exception frame only in RaiseIndexError. I have changed the procedure. Michael. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TList slowness in classes
On Fri, 24 Dec 2004 11:49:10 +0100 (W. Europe Standard Time) Michael Van Canneyt <[EMAIL PROTECTED]> wrote: > > > On Fri, 24 Dec 2004, Mattias Gaertner wrote: > > > On Fri, 24 Dec 2004 10:56:24 +0100 (W. Europe Standard Time) > > Michael Van Canneyt <[EMAIL PROTECTED]> wrote: > > > > > > If the answer is yes, then maybe it's safe to compile parts of FPC > > > > sources in lists.inc (like TList.Get) inside {$IMPLICITEXCEPTIONS OFF} ? > > > > Why not put it into a sub proc: > > > > function TList.Get(Index: Integer): Pointer; > > > > procedure RaiseIndexError; > > begin > > Error(SListIndexError,Index); > > end; > > > > begin > > If (Index<0) or (Index>=FCount) then > > RaiseIndexError; > > Result:=FList^[Index]; > > end; > > > > The compiler detects that the sub can raise an exception. And creates the implicit exception frame only in RaiseIndexError. Mattias ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TList slowness in classes
Michael Van Canneyt wrote: On Fri, 24 Dec 2004, Mattias Gaertner wrote: On Fri, 24 Dec 2004 10:56:24 +0100 (W. Europe Standard Time) Michael Van Canneyt <[EMAIL PROTECTED]> wrote: If the answer is yes, then maybe it's safe to compile parts of FPC sources in lists.inc (like TList.Get) inside {$IMPLICITEXCEPTIONS OFF} ? Why not put it into a sub proc: function TList.Get(Index: Integer): Pointer; procedure RaiseIndexError; begin Error(SListIndexError,Index); end; begin If (Index<0) or (Index>=FCount) then RaiseIndexError; Result:=FList^[Index]; end; The compiler detects that the sub can raise an exception. But in the main procedure there is no need for an implicit try..finally block, is there? Vincent. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TList slowness in classes
On Fri, 24 Dec 2004, Mattias Gaertner wrote: > On Fri, 24 Dec 2004 10:56:24 +0100 (W. Europe Standard Time) > Michael Van Canneyt <[EMAIL PROTECTED]> wrote: > > > > If the answer is yes, then maybe it's safe to compile parts of FPC > > > sources in lists.inc (like TList.Get) inside {$IMPLICITEXCEPTIONS OFF} ? > > Why not put it into a sub proc: > > function TList.Get(Index: Integer): Pointer; > > procedure RaiseIndexError; > begin > Error(SListIndexError,Index); > end; > > begin > If (Index<0) or (Index>=FCount) then > RaiseIndexError; > Result:=FList^[Index]; > end; > The compiler detects that the sub can raise an exception. Michael. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TList slowness in classes
On Fri, 24 Dec 2004 10:56:24 +0100 (W. Europe Standard Time) Michael Van Canneyt <[EMAIL PROTECTED]> wrote: > > If the answer is yes, then maybe it's safe to compile parts of FPC > > sources in lists.inc (like TList.Get) inside {$IMPLICITEXCEPTIONS OFF} ? Why not put it into a sub proc: function TList.Get(Index: Integer): Pointer; procedure RaiseIndexError; begin Error(SListIndexError,Index); end; begin If (Index<0) or (Index>=FCount) then RaiseIndexError; Result:=FList^[Index]; end; ? Mattias ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TList slowness in classes
Michalis Kamburelis wrote: Hi, I tested your code and found that indeed version in ucopylist is slightly faster (by about 9.5 / 7 =~ 1.357). Two things: 1. Speedup is only 1.357x, not 3x, like you said. Are you sure that you're getting 3x speedup ? On what OS and with what FPC version are you testing this ? I was doing tests with Linux/i386 with FPC 1.9.4 and 1.9.5 (from CVS 2004-12-20). 2. Still, speedup 1.357x may be significant in some cases so I investigated what's the cause: After many tests I found that this slight speedup is caused by the fact that in ucopylist you declared string constants SListIndexError, SListCapacityError and SListCountError as normal constants while with original Classes unit these constants are taken from RTLConst unit that defines them as resourcestrings. Using resourcestrings in RTL is a must, since this allows to translate error messages without modifying unit Classes sources. However in this case exceptions are not raised, so resourcestrings are not actually used. But it looks that any procedure that uses some resourcestring in implementation is doomed to be slower than the similar procedure that instead uses normal string consts, *even if this procedure doesn't actually access the string at runtime*. It seems that if some procedure uses resourcestring then upon entry it does some lengthy initialization of this resourcestring, even if it will not actually make use of that resourcestring. I'm attaching a simple demo program that shows this. When compiled like fpc -OG -O2 -Op2 demo_resourcestring_slow.pas (to get maximum optimizations) sample output of it is Time of Foo_Normal: 16 Time of Foo_ResourceString: 106 So time difference is really noticeable. Question goes to FPC developers, maybe such cases with using resourcestrings can be speed up ? Regards, {$mode objfpc}{$H+} uses {BaseUnix, Unix needed only to implement Clock} BaseUnix, Unix, SysUtils; function Clock: Int64; var Dummy: tms; begin Clock := FpTimes(Dummy); end; const SNormal= 'blah blah blah blah blah blah blah blah blah blah'; resourcestring SResString = 'blah blah blah blah blah blah blah blah blah blah'; { Foo_Normal and Foo_ResourceString do the same thing, but Foo_Normal uses normal string constant while Foo_ResourceString uses resourcestring. } procedure Foo_Normal(i: Integer); begin if i = -1 then raise Exception.Create(SNormal); end; procedure Foo_ResourceString(i: Integer); begin if i = -1 then raise Exception.Create(SResString); end; { Note that when I call Foo_Normal and Foo_ResourceString i is always >= 0 so Exception is never actually raised. So string constants SNormal and SResString are not really used. } const TestCount = 1000; var i: Integer; Start: Int64; begin Start := Clock; for i := 0 to TestCount do Foo_Normal(i); Writeln('Time of Foo_Normal: ', Clock - Start); Start := Clock; for i := 0 to TestCount do Foo_ResourceString(i); Writeln('Time of Foo_ResourceString: ', Clock - Start); end. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel The slowness 3x I ment was not between atomics like get/put but when I tested a bigger(1x1) bubblesort with the copy and original. The times back then I got were about: Original: ~28seconds Copy: ~6seconds This is even more than 3x.(ups ;-) ) In any case the point is in critical operations these things can be real problematic. Another interresting fact is that ListArray from java(almost same thing as our TList) was about 8 seconds with same test. Don't get me wrong, I'm not trying to reasure myself here, it's just that I think it can be made faster nothing else. The resourcestrings are interresting. I'd look at the code but I'm afraid that's a bit too deep RTL for me... Ales ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TList slowness in classes
On Fri, 24 Dec 2004, Michalis Kamburelis wrote: > Peter Vreman wrote: > >>>This is because there is an extra (implicit) Try/Finally block. > >> > >>Thank you and Peter for answers. This way I was able to see how > >>try...finally section looks in assembler :) Anyway, I understand that > >>the answer is "can't be speed up". OK, I can live with that. > > > > > > That is not correct. For your own code you can disable the implicit > > exception frame with a directive: > > > > {$IMPLICITEXCEPTIONS OFF} > > > > Indeed when I put {$IMPLICITEXCEPTIONS OFF} at the beginning of > demo_resourcestring_slow.pas, Foo_Normal and Foo_ResourceString work > equally fast. Nice, that's a solution in cases when I know that some > code will not exit with exception. > > But I risk that if I ever call Foo_ResourceString(-1) that will raise > exception from Foo_ResourceString, I can get memory leaks, right ? Yes > Or can I predict in certain cases that using {$IMPLICITEXCEPTIONS OFF} is > safe (no memory leaks) even when procedure will raise some exceptions ? In this particular case you will get memory leaks. As soon as an ansistring is used, you will have problems. > If the answer is yes, then maybe it's safe to compile parts of FPC > sources in lists.inc (like TList.Get) inside {$IMPLICITEXCEPTIONS OFF} ? Normally not. Michael. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TList slowness in classes
Peter Vreman wrote: This is because there is an extra (implicit) Try/Finally block. Thank you and Peter for answers. This way I was able to see how try...finally section looks in assembler :) Anyway, I understand that the answer is "can't be speed up". OK, I can live with that. That is not correct. For your own code you can disable the implicit exception frame with a directive: {$IMPLICITEXCEPTIONS OFF} Indeed when I put {$IMPLICITEXCEPTIONS OFF} at the beginning of demo_resourcestring_slow.pas, Foo_Normal and Foo_ResourceString work equally fast. Nice, that's a solution in cases when I know that some code will not exit with exception. But I risk that if I ever call Foo_ResourceString(-1) that will raise exception from Foo_ResourceString, I can get memory leaks, right ? Or can I predict in certain cases that using {$IMPLICITEXCEPTIONS OFF} is safe (no memory leaks) even when procedure will raise some exceptions ? If the answer is yes, then maybe it's safe to compile parts of FPC sources in lists.inc (like TList.Get) inside {$IMPLICITEXCEPTIONS OFF} ? -- Michalis ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TList slowness in classes
>> This is because there is an extra (implicit) Try/Finally block. > > Thank you and Peter for answers. This way I was able to see how > try...finally section looks in assembler :) Anyway, I understand that > the answer is "can't be speed up". OK, I can live with that. That is not correct. For your own code you can disable the implicit exception frame with a directive: {$IMPLICITEXCEPTIONS OFF} ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TList slowness in classes
Michael Van Canneyt wrote: On Fri, 24 Dec 2004, Michalis Kamburelis wrote: Hi, I tested your code and found that indeed version in ucopylist is slightly faster (by about 9.5 / 7 =~ 1.357). Two things: 1. Speedup is only 1.357x, not 3x, like you said. Are you sure that you're getting 3x speedup ? On what OS and with what FPC version are you testing this ? I was doing tests with Linux/i386 with FPC 1.9.4 and 1.9.5 (from CVS 2004-12-20). 2. Still, speedup 1.357x may be significant in some cases so I investigated what's the cause: After many tests I found that this slight speedup is caused by the fact that in ucopylist you declared string constants SListIndexError, SListCapacityError and SListCountError as normal constants while with original Classes unit these constants are taken from RTLConst unit that defines them as resourcestrings. Using resourcestrings in RTL is a must, since this allows to translate error messages without modifying unit Classes sources. However in this case exceptions are not raised, so resourcestrings are not actually used. But it looks that any procedure that uses some resourcestring in implementation is doomed to be slower than the similar procedure that instead uses normal string consts, *even if this procedure doesn't actually access the string at runtime*. It seems that if some procedure uses resourcestring then upon entry it does some lengthy initialization of this resourcestring, even if it will not actually make use of that resourcestring. This is because there is an extra (implicit) Try/Finally block. Michael. Thank you and Peter for answers. This way I was able to see how try...finally section looks in assembler :) Anyway, I understand that the answer is "can't be speed up". OK, I can live with that. -- Michalis ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TList slowness in classes
On Fri, 24 Dec 2004, Michalis Kamburelis wrote: > Hi, > > I tested your code and found that indeed version in ucopylist is > slightly faster (by about 9.5 / 7 =~ 1.357). Two things: > > 1. Speedup is only 1.357x, not 3x, like you said. Are you sure that > you're getting 3x speedup ? On what OS and with what FPC version are you > testing this ? I was doing tests with Linux/i386 with FPC 1.9.4 and > 1.9.5 (from CVS 2004-12-20). > > 2. Still, speedup 1.357x may be significant in some cases so I > investigated what's the cause: > > After many tests I found that this slight speedup is caused by the fact > that in ucopylist you declared string constants SListIndexError, > SListCapacityError and SListCountError as normal constants while with > original Classes unit these constants are taken from RTLConst unit that > defines them as resourcestrings. > > Using resourcestrings in RTL is a must, since this allows to translate > error messages without modifying unit Classes sources. > > However in this case exceptions are not raised, so resourcestrings are > not actually used. But it looks that any procedure that uses some > resourcestring in implementation is doomed to be slower than the similar > procedure that instead uses normal string consts, *even if this > procedure doesn't actually access the string at runtime*. It seems that > if some procedure uses resourcestring then upon entry it does some > lengthy initialization of this resourcestring, even if it will not > actually make use of that resourcestring. This is because there is an extra (implicit) Try/Finally block. Michael. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TList slowness in classes
> I'm attaching a simple demo program that shows this. When compiled like >fpc -OG -O2 -Op2 demo_resourcestring_slow.pas > (to get maximum optimizations) sample output of it is >Time of Foo_Normal: 16 >Time of Foo_ResourceString: 106 > So time difference is really noticeable. Question goes to FPC > developers, maybe such cases with using resourcestrings can be speed up ? You can compile with -al and run a diff between the generated .s files. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TList slowness in classes
Hi, I tested your code and found that indeed version in ucopylist is slightly faster (by about 9.5 / 7 =~ 1.357). Two things: 1. Speedup is only 1.357x, not 3x, like you said. Are you sure that you're getting 3x speedup ? On what OS and with what FPC version are you testing this ? I was doing tests with Linux/i386 with FPC 1.9.4 and 1.9.5 (from CVS 2004-12-20). 2. Still, speedup 1.357x may be significant in some cases so I investigated what's the cause: After many tests I found that this slight speedup is caused by the fact that in ucopylist you declared string constants SListIndexError, SListCapacityError and SListCountError as normal constants while with original Classes unit these constants are taken from RTLConst unit that defines them as resourcestrings. Using resourcestrings in RTL is a must, since this allows to translate error messages without modifying unit Classes sources. However in this case exceptions are not raised, so resourcestrings are not actually used. But it looks that any procedure that uses some resourcestring in implementation is doomed to be slower than the similar procedure that instead uses normal string consts, *even if this procedure doesn't actually access the string at runtime*. It seems that if some procedure uses resourcestring then upon entry it does some lengthy initialization of this resourcestring, even if it will not actually make use of that resourcestring. I'm attaching a simple demo program that shows this. When compiled like fpc -OG -O2 -Op2 demo_resourcestring_slow.pas (to get maximum optimizations) sample output of it is Time of Foo_Normal: 16 Time of Foo_ResourceString: 106 So time difference is really noticeable. Question goes to FPC developers, maybe such cases with using resourcestrings can be speed up ? Regards, -- Michalis Ales Katona wrote: I've read a complaint about TList being slow so I decided to give it a test. Quite frankly the test showed this is truth, but I couldn't find out why. I found out that if I copy the TList from classes "as-is" into my unit and use this copy, it is about 3x faster in certain conditions. I have no idea why this is so but I think there's something wrong... I posted my test at http://members.chello.sk/ales/testlist.zip Just download, unzip and compile: you'll get swap time and access time for the original TList uncomment {$DEFINE USEMYLIST} to get the times for my copy of TList The copy there is unchanged. Ales Katona ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel {$mode objfpc}{$H+} uses {BaseUnix, Unix needed only to implement Clock} BaseUnix, Unix, SysUtils; function Clock: Int64; var Dummy: tms; begin Clock := FpTimes(Dummy); end; const SNormal= 'blah blah blah blah blah blah blah blah blah blah'; resourcestring SResString = 'blah blah blah blah blah blah blah blah blah blah'; { Foo_Normal and Foo_ResourceString do the same thing, but Foo_Normal uses normal string constant while Foo_ResourceString uses resourcestring. } procedure Foo_Normal(i: Integer); begin if i = -1 then raise Exception.Create(SNormal); end; procedure Foo_ResourceString(i: Integer); begin if i = -1 then raise Exception.Create(SResString); end; { Note that when I call Foo_Normal and Foo_ResourceString i is always >= 0 so Exception is never actually raised. So string constants SNormal and SResString are not really used. } const TestCount = 1000; var i: Integer; Start: Int64; begin Start := Clock; for i := 0 to TestCount do Foo_Normal(i); Writeln('Time of Foo_Normal: ', Clock - Start); Start := Clock; for i := 0 to TestCount do Foo_ResourceString(i); Writeln('Time of Foo_ResourceString: ', Clock - Start); end.___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
[fpc-devel] TList slowness in classes
I've read a complaint about TList being slow so I decided to give it a test. Quite frankly the test showed this is truth, but I couldn't find out why. I found out that if I copy the TList from classes "as-is" into my unit and use this copy, it is about 3x faster in certain conditions. I have no idea why this is so but I think there's something wrong... I posted my test at http://members.chello.sk/ales/testlist.zip Just download, unzip and compile: you'll get swap time and access time for the original TList uncomment {$DEFINE USEMYLIST} to get the times for my copy of TList The copy there is unchanged. Ales Katona ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel