Visit our Sponsor   Visit our Sponsor
delphi3000.com - the free delphi knowledge platform
delphi3000.com - the free delphi knowledge platform
Have a look at your member-status

connecting people's knowledge


  - Recent ArticlesRSS feed for Recent Articles on delphi3000.com
  - List of All Articles
  - Top Viewed Articles
  - Articles (+Attachem.)
  - Articles Of Interest
  - Categories
  - Top Uploader
  - Search
  - Index

  - My Home
  - Submit an Article
  - My Articles
  - My Personal Data
  - My Bookmarks
  - Activities
  - Login/Logout

  - Sign Up
  - Why Sign Up
  - Newsletter

  - Press
  - Advertise

  - Contact
  - Feedback





Community
Borland
ClubeDelphi
Dr. Bob
UK-BUG
Delphi Meetings
Planeta Delphi







Startblatt.de






Share this article with friendsShare this article with friends
Rate this articleRate this article - to keep the quality of delphi3000.com !
Comment this article or read through previous comments (2)


Delphi 3,4,5 TCollection Performance Issues and SolutionsGo to Clever Components's websiteComponent available for this articleFormat this article printer-friendly!Bookmark function is only available for registered users!
Product:
Delphi 3.x (or higher)
Category:
Object Pascal
Skill Level:
Scoring:
Last Update:
06/27/2002
Search Keys:
delphi delphi3000 article borland vcl code-snippet Delphi 3 4 5 TCollection Performance Issues Solutions Bugs Speed Fast Slow How To Sources
Times Scored:
8
Visits:
4703
Uploader: Clever Components
Company: CleverComponents
Reference: CleverComponents.com
Component Download: http://www.clevercomponents.com/articles/article008/collectionperf.asp
 
Question/Problem/Abstract:
Delphi 3,4,5 TCollection Performance Issues and Solutions
Answer:



Delphi 3,4,5 TCollection Performance Issues and Solutions

If you are using TCollection classes in your Delphi 3,4 or 5 applications than you will find this article quite interesting.

Firstly let us try fairly simple code:

procedure TForm1.Button1Click(Sender: TObject);
var
   old: TCollection;
   i: integer;
begin
   old := TCollection.Create(TCollectionItem);
   for i := 0 to 100000 do
   begin
      old.Add;
   end;
   Windows.beep(900, 1000); // hi-freq beep after we done with adding empty items
   old.Free;
   Windows.beep(100, 1000);// low-freq beep after we done with destroying empty items
end;  

You might think that low-freq beep will follow right after hi-freq beep (well what can be faster that just simply destroy all collection items) - but IT IS not!

In fact it takes 10-20 seconds to destroy collection which hold few dozen thousands items - and worse of all your CPU will be 100% busy. We bumped into this problem when our clients complains that application is "freeze PC for a few minutes".

To understand why it is happening you need take closer look at TCollectionItem.Destroy, TCollectionItem.SetCollection and TCollection.RemoveItem functions which located at classes.pas - last one is the key to understanding this problem.

You also might want to compare your TCollection.RemoveItem version to Delphi 6 TCollection.RemoveItem code:

{ classes.pas from Delphi 6 }
procedure TCollection.RemoveItem(Item: TCollectionItem);
begin
   Notify(Item, cnExtracting);
   if Item = FItems.Last then
      FItems.Delete(FItems.Count - 1) // that will fix original problem
   else
      FItems.Remove(Item);
   Item.FCollection := nil;
   NotifyDesigner(Self, Item, opRemove);
   Changed;
end;  

Now you probably will want to fix it. But seems it is not so easy because TCollection.RemoveItem is not a virtual or dynamic function.

Here is two solutions:

You will need to alter classes.pas - put that TCollection.RemoveItem code from Delphi 6 into your version of classes.pas.

Copy new (fixed) classes.pas into your project directory and put it at the first position in your .dpr uses section like this:

program Project1;

uses
   classes in 'classes.pas' // new classes.pas with fixed TCollection.RemoveItem
   Forms,
   Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

begin
   Application.Initialize;
   Application.CreateForm(TForm1, Form1);
   Application.Run;
end.  

Now your project will be compiled with new version of TCollection.

In some situations it is not so convenient or even not possible to use altered classes.pas and in this case we have other trick for you.

type
{ TFixCollection - fix TCollection.RemoveItem issue in Delphi 3,4,5 }
   TFixCollection = class(TCollection)
   public
   { Unfortunately Clear is not a virtual or dynamic procedure so we will have to reintroduce it }
      procedure Clear;
      destructor Destroy; override;
   end;

procedure TFixCollection.Clear;
var
   i: integer;
   AList, OrgList: TList;
begin
   AList := TList.Create;
   try
      OrgList := TList(PDWORD(DWORD(Self) + $4 + SizeOf(TPersistent))^);

      { Save original pointers to collection items }
      for i := 0 to OrgList.Count-1 do
         AList.Add(OrgList[i]);

      OrgList.Clear;

      { Destroy collection items }
      for i := 0 to AList.Count-1 do
         TCollectionItem(AList[i]).Free;
   finally
      AList.Free;
   end;
   inherited;
end;

destructor TFixCollection.Destroy;
begin
   Clear;
   inherited;
end;

{ Let's try again ! }
procedure TForm1.Button2Click(Sender: TObject);
var
   old: TFixCollection;
   i: integer;
begin
   old := TFixCollection.Create(TCollectionItem);
   for i := 0 to 100000 do
      old.Add;
   Windows.beep(900, 1000); // hi-freq beep after we done with adding empty items
   old.Free;
   Windows.beep(100, 1000);// low-freq beep after we done with destroying empty items
end;  

As you can see now it works just fine. We used one trick which gives us access to protected section of TCollection.

You can use both techniques in your applications written on Delphi versions 3,4,5.

For your convenience you can download Delphi 3,4,5 TCollection performance issue demo sources here CollectionPerformanceDemo.zip

Please see original article for more at our website.

Clever Components Support Team.
www.CleverComponents.com.
info@clevercomponents.com.





Please rate this article!
Skill level:
BeginnerExpert

Useful:
No!Very!

Overall rating:
PoorExcellent



Comments to this article
Write a new comment
Where is Classes.pas?
    Mike Trim (Jul 1 2002 3:39PM)

I don't have it in the Source/Rtl/ dir
Respond

RE: Where is Classes.pas?
Clever Components (Jul 1 2002 11:31PM)

Dear Mike,

You probably forgot to select "Install Sources" option during installation.

Best Regards,

Clever Components Team
info@CleverComponents.com
www.CleverComponents.com
Respond














 
Sign up to consume product discounts for Bronze memberships !

read more


  Visit our Sponsor

 

  Community Ad of
L. Rosenstein
 
   














 







     
  Copyright © 2000 - 2007 delphi3000.com - All rights reserved. Terms of use. || Privacy
delphi3000.com is a service by bluestep.com IT-Services GmbH (Vienna)