Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2011-06

Inserting many components on form

13 messages · 8 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Unknown author

I wrote a component editor that can insert some components on a form or data module. But when I insert many components, the performance of lazarus is terrible. Inserting 510 components on my I5 540M with 8Gb of Ram takes 14 seconds. If I try insert 1020 components, this action takes 52 seconds. If I try insert 4000 components, I don't know how many time this action takes, because it freezes the Lazarus for a long time.

My component editor class has two methods:

procedure TInsertTagsOnFormComponentEditor.AddTagInEditor(Tag:TTag);
{$IFDEF FPC}
var
 Hook: TPropertyEditorHook;
{$ENDIF}
begin
{$IFDEF FPC}
 Hook:=nil;
 if not GetHook(Hook) then exit;
 Hook.PersistentAdded(Tag,false);
 Modified;
{$ELSE}
 Designer.Modified;
{$ENDIF}
end;
function
 TInsertTagsOnFormComponentEditor.CreateComponent(tagclass:TComponentClass):TComponent;
begin
 {$IFDEF FPC}
   Result := tagclass.Create(GetTheOwner);
 {$ELSE}
   Result := Designer.CreateComponent(tagclass,GetTheOwner,0,0,0,0);
 {$ENDIF}
end;

To use this editor, the component wizard call (to each component created):

obj:= componentClass(compeditor.CreateComponent(componentClass));
compeditor.AddTagInEditor(obj);

Somebody did something like this? Am I doing something wrong? What's the Lazarus pieces that mus be improved to perform this action more fastest?

The best regards,

Fabio
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20110627/e600ce25/attachment.html>

Reply by email

Mattias Gaertner
to Unknown author
Show quoted text 9 lines
I wrote a component editor that can insert some components on a form or data module. But when I insert many components, the performance of lazarus is terrible. Inserting 510 components on my I5 540M with 8Gb of Ram takes 14 seconds. If I try insert 1020 components, this action takes 52 seconds. If I try insert 4000 components, I don't know how many time this action takes, because it freezes the Lazarus for a long time. [...] Somebody did something like this? Am I doing something wrong? What's the Lazarus pieces that mus be improved to perform this action more fastest?

TComponent uses linear searches/notifications for each operation. So 1000 components is a bad idea.
LCL adds even more searches/notifications, so 300 components is a bad idea.

Mattias

Reply by email

Unknown author
to Mattias Gaertner

2011/6/27 Mattias Gaertner

Show quoted text 7 lines
TComponent uses linear searches/notifications for each operation. So 1000 components is a bad idea. LCL adds even more searches/notifications, so 300 components is a bad idea.

And to make 4000 or 10000 components a good idea, what's must be changed?

To take as parameter, Delphi 7 breaks near of 500 inserted components. Lazarus wins!

Fabio
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20110627/678a8898/attachment.html>

Reply by email

Mattias Gaertner
to Unknown author
Show quoted text 10 lines
2011/6/27 Mattias Gaertner > > TComponent uses linear searches/notifications for each operation. So > 1000 components is a bad idea. > LCL adds even more searches/notifications, so 300 components is a bad > idea. > > And to make 4000 or 10000 components a good idea, what's must be changed?

A lot.
Are you sure you need that many components? For example some components uses TCollection and other classes to handle thousands of objects. Maybe if you explain what you want to achieve people can give an advice.

To take as parameter, Delphi 7 breaks near of 500 inserted components.Lazarus wins!

:)

Mattias

Reply by email

Unknown author
to Mattias Gaertner

2011/6/27 Mattias Gaertner

Show quoted text 20 lines
On Mon, 27 Jun 2011 16:31:56 -0300 "" wrote: > 2011/6/27 Mattias Gaertner > > > > > TComponent uses linear searches/notifications for each operation. So > > 1000 components is a bad idea. > > LCL adds even more searches/notifications, so 300 components is a bad > > idea. > > > > > And to make 4000 or 10000 components a good idea, what's must be changed? A lot. Are you sure you need that many components? For example some components uses TCollection and other classes to handle thousands of objects. Maybe if you explain what you want to achieve people can give an advice.

Maybe I started my components with a wrong concept. Each component, represents a memory (or a set of memories) on a remote device (like a PLC) that can be read and/or written. These components can be linked with edits, labels, progress bars and others controls created to show/modifies/stores the value of these components.

For now, I did only small projects using these components (using ~150 tags or components). Today, I started my first big project. On the first time, using the component wizard, I inserted 255*5+1 components. This action takes some time. After this, I tried using my wizard again, to insert 4000 components, and after this the IDE freezes.

I thought use the TCollection, but I don't know if I can represent the following configuration (it's a example, it can have how many PLCBlocks, BlockItems, TagBit, PLCNumbers or PLCStrings the owner of project wants):

Owner (TCollection)
|
|-> PLCBlock (now, each below is a component)
| |
| |-> BlockItem (0..n items)
| |-> BlockItem
| | |
| | |-> TagBit (0..n items)
|
|-> PLCBlock
| |
| |-> BlockItem (0..n items)
|
|-> PLCNumber (0..n items)
| |-> TagBit (0..n items)
|
|-> PLCString (0..n items)

Some idea?

The best regards,

Fabio
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20110627/9eb7fa0d/attachment-0001.html>

Reply by email

Michael Van Canneyt
to Unknown author
Show quoted text 53 lines
2011/6/27 Mattias Gaertner On Mon, 27 Jun 2011 16:31:56 -0300 "" wrote: > 2011/6/27 Mattias Gaertner > > > > > TComponent uses linear searches/notifications for each operation. So > > 1000 components is a bad idea. > > LCL adds even more searches/notifications, so 300 components is a bad > > idea. > > > > > And to make 4000 or 10000 components a good idea, what's must be changed? A lot. Are you sure you need that many components? For example some components uses TCollection and other classes to handle thousands of objects. Maybe if you explain what you want to achieve people can give an advice. Maybe I started my?components?with a wrong concept. Each component, represents a memory (or a set of memories) on a remote device (like a PLC) that can be read and/or written. These components can be linked with edits, labels, progress bars and others controls created to show/modifies/stores the value of these components. For now, I did only small projects using these components (using ~150 tags or components). Today, I started my first big project. On the first time, using the component wizard, I inserted 255*5+1 components. This action takes some time. After this, I tried using my wizard again, to insert 4000 components, and after this the IDE freezes.? I thought use the TCollection, but I don't know if I can represent the following configuration (it's a example, it can have how many PLCBlocks, BlockItems, TagBit,?PLCNumbers or?PLCStrings the owner of project wants): Owner (TCollection) ? ?| ? ?|-> PLCBlock (now, each below is a component) ? ?| ? ? ? | ? ?| ? ? ? |->?BlockItem?(0..n items) ? ?| ? ? ? |->?BlockItem ? ?| ? ? ? | ? ? ? |?? ? ?| ? ? ? | ? ? ? |-> TagBit?(0..n items) ? ?| ? ?|-> PLCBlock ? ?| ? ? ? | ? ?| ? ? ? |-> BlockItem?(0..n items)?? ? ?| ? ?|-> PLCNumber?(0..n items) ? ?| ? ? ? |-> TagBit?(0..n items) ? ?| ? ?|-> PLCString (0..n items) Some idea?

In a collection that is written to stream, all items must be of the same type, because when reconstructing the collection, 'Add' is called.

There are 2 ways out of this:
- Merge PLCBlock, PLCNumber, PLCString to a single type
- Create different collections, each with a unique type.

If you absolutely need different types, you'll need different collections.

Then, there is nothing to stop you from nesting collections. i.e. PLCBlock can have a collection BLockItems which contains items of class BlockItem. They will be streamed correctly.

But the fastest (in terms of streaming and code speed) may be to have something like a TTreeNode object, and use DefineProperties to stream it. That's of course more coding for you.

Michael.

Reply by email

Martin
to Michael Van Canneyt
Michael Van Canneyt wrote 28 lines
> I thought use the TCollection, but I don't know if I can represent > the following configuration (it's a example, it can have how many > PLCBlocks, BlockItems, > TagBit, PLCNumbers or PLCStrings the owner of project wants): > > Owner (TCollection) > | > |-> PLCBlock > | | > | |-> BlockItem (0..n items) > | > |-> PLCNumber (0..n items) > | |-> TagBit (0..n items) > | > |-> PLCString (0..n items) > > Some idea? In a collection that is written to stream, all items must be of the same type, because when reconstructing the collection, 'Add' is called. There are 2 ways out of this: - Merge PLCBlock, PLCNumber, PLCString to a single type - Create different collections, each with a unique type. If you absolutely need different types, you'll need different collections.

You can also define a special CollectionItem, that has a published property for each of the possible types.
And then have an prop-editor that hides this away.

However, it does not fully solve the issue.
If your objects need to interact with other Components such as TEdit... then you need to register a Notification anyway => so your object learns if the Edit is destroyed (otherwise you may get a dangling pointer)

Show quoted text 8 lines
Then, there is nothing to stop you from nesting collections. i.e. PLCBlock can have a collection BLockItems which contains items of class BlockItem. They will be streamed correctly. But the fastest (in terms of streaming and code speed) may be to have something like a TTreeNode object, and use DefineProperties to stream it. That's of course more coding for you.

You can also look at what TSynEdit does for the gutter (Gutterparts). They are still components, but IIRC the ownership is no longer with the form => that ultimately should reduce the size of some of the big lists (e.g notification list, child list, ....)

That is normally all components are owned by the form, so they are all in the component-list of the form, but if they are owned by an other component (or several).....

But you need to get to know some of the details of streaming...

Reply by email

Mattias Gaertner
to Martin
Show quoted text 18 lines
On 27/06/2011 22:17, Michael Van Canneyt wrote: >> I thought use the TCollection, but I don't know if I can represent >> the following configuration (it's a example, it can have how many >> PLCBlocks, BlockItems, >> TagBit, PLCNumbers or PLCStrings the owner of project wants): >> >> Owner (TCollection) >> | >> |-> PLCBlock >> | | >> | |-> BlockItem (0..n items) >> | >> |-> PLCNumber (0..n items) >> | |-> TagBit (0..n items) >> | >> |-> PLCString (0..n items) >> >> Some idea?

And what is the reason to store this data as form data?

Mattias

Reply by email

Unknown author
to Mattias Gaertner

2011/6/27 Mattias Gaertner

And what is the reason to store this data as form data?

As I said: Maybe I started my components with a wrong concept. I'll study a way to use collections instead of component. I'll consider too, a way to move a collection item between collections.

The best regards,

Fabio
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20110627/92a20b7e/attachment.html>

Reply by email

Hans-Peter Diettrich
to Unknown author: 2011/6/27 Mattias Gaertner Maybe I started my components with a wrong concept. Each…
Show quoted text 5 lines
Maybe I started my components with a wrong concept. Each component, represents a memory (or a set of memories) on a remote device (like a PLC) that can be read and/or written. These components can be linked with edits, labels, progress bars and others controls created to show/modifies/stores the value of these components.

I'd "virtualize" the GUI, so that not every item is represented by a different component. It may help to store the items in a database, instead of using the component streaming mechanism and resource files.

It's okay to use components (i.e. controls) for the GUI, but these should be limited to the required representation (dialogs...) of the data items. Then configure the visible controls to show the data for the currently selected item.

DoDi

Reply by email

Fabio Luis Girardi
to Hans-Peter Diettrich

I found another way to do this: extend the TCollection and write a new procedure Add to allow choose what's the item class the user wants create and make a Property editor for this new Collection class, that will call this new Add method (yes, can be more easy if the Add procedure of the TCollection as set as virtual, but...). Finally, my tags will be a descendant of TCollectionItem class. It isn't hard to do, and keep the features of TCollection.

I'll start the implementation of this new idea, and post the result here.

Regards,

Fabio

2011/6/28 Hans-Peter Diettrich :

Show quoted text 20 lines
schrieb: > Maybe I started my components with a wrong concept. Each component, > represents a memory (or a set of memories) on a remote device (like a PLC) > that can be read and/or written. These components can be linked with edits, > labels, progress bars and others controls created to show/modifies/stores > the value of these components. I'd "virtualize" the GUI, so that not every item is represented by a different component. It may help to store the items in a database, instead of using the component streaming mechanism and resource files. It's okay to use components (i.e. controls) for the GUI, but these should be limited to the required representation (dialogs...) of the data items. Then configure the visible controls to show the data for the currently selected item. DoDi

Reply by email

Max Vlasov
to Fabio Luis Girardi
Fabio Luis Girardi wrote 5 lines
I found another way to do this: extend the TCollection and write a new procedure Add to allow choose what's the item class the user wants create and make a Property editor for this new Collection class, that will call this new Add method (yes, can be more easy if the Add procedure of the TCollection as set as virtual, but...).

Fabio, as long as I remember, currently there's no typeinfo stored for particualar collection item (you can look at any dfm or lfm containing collections), so you will probably lose the type difference when you collection is loaded. If it's hard to solve, I remember I experimented with persistents (like TFont) being different types for the same owner component type so you can use a property in the common collection item that defines the type and this property recreate a persistent being other property of the same item.

Max

Reply by email

Alexander Klenin
to Fabio Luis Girardi: I found another way to do this: extend the TCollection and write a new procedure Add to…
Fabio Luis Girardi wrote 9 lines
I found another way to do this: extend the TCollection and write a new procedure Add to allow choose what's the item class the user wants create and make a Property editor for this new Collection class, that will call this new Add method (yes, can be more easy if the Add procedure of the TCollection as set as virtual, but...). Finally, my tags will be a descendant of TCollectionItem class. It isn't hard to do, and keep the features of TCollection. I'll start the implementation of this new idea, and post the result here.

I have missed your original mail, but if I understand you correctly, you might me interested to look at series in TChart.

Alexander S. Klenin

Reply by email