Jump to content

how to increase performance of runTime-created components...


erich.wanker

Recommended Posts

Hello folks,

 

i am playing with runtime-created components ...but the create-performance is very slow ..

 

What can i do to optimize the following codelines ?

 

Thanx for helping :-)

Erich

 

 
procedure TtestFrame(wo_01:TUniPanel);
begin




// CREATE THE MAIN UNIPANEL
my_structure_01:=tuniPanel.Create(self);
my_structure_01.Parent:=wo_01;
my_structure_01.Left:=0;
my_structure_01.Width:=wo_01.Width;
my_structure_01.Top:=abstand_01;
my_structure_01.Height:=wo_01.Height-my_structure_01.Top;
my_structure_01.ShowCaption:=false;
my_structure_01.BorderStyle:=ubsNone;
my_structure_01.Color:=normal_rgb_01; //clwhite;


// DATABASE LOOP
unimainmodule.ZVERTRAG.first;
while not unimainmodule.ZVERTRAG.Eof do
begin


        // USE A PANEL AS ONE RECORD
        my_uniPanel_01:=tuniPanel.Create(my_structure_01);
        my_uniPanel_01.Parent:=my_structure_01;
        my_uniPanel_01.Left:=0;
        my_uniPanel_01.Width:=my_structure_01.Width;
        my_uniPanel_01.Top:=position_01;
        my_uniPanel_01.Height:=hoehe_01;
        my_uniPanel_01.Caption:=unimainmodule.ZVERTRAG.fieldbyname('STRUCTURE_NR').AsString;
        my_uniPanel_01.Tag:=unimainmodule.ZVERTRAG.fieldbyname('STRUCTURE_NR').AsInteger;
        my_uniPanel_01.OnClick:=my_panel_click_01;
        my_uniPanel_01.ShowCaption:=false;
        my_uniPanel_01.BorderStyle:=ubsNone;
        my_uniPanel_01.Cursor:=crHandPoint;
        my_uniPanel_01.Name:='MY_01_'+unimainmodule.ZVERTRAG.fieldbyname('STRUCTURE_NR').AsString;
                my_uniPanel_01.ClientEvents.ExtEvents.Add
                ('OnAfterrender=function OnAfterrender(sender)'+
                ' {document.getElementById(sender.body.id).className ="hoverpanel"; }');
                my_uniPanel_01.ClientEvents.UniEvents.Add
                ('OnAfterCreate=function OnAfterCreate(sender)'+
                ' {sender.cls="myUnselectable"; }');




        // A SMALL IMAGE
        my_uniimage_01:=TuniImage.Create(self);
        my_uniimage_01.Parent:=my_uniPanel_01;
        my_uniimage_01.Picture.LoadFromFile(uniServerModule.FilesFolderPath+'folder_orange_leer.gif');
        my_uniimage_01.Width:=18;
        my_uniimage_01.Height:=16;
        my_uniimage_01.Left:=5;
        my_uniimage_01.Top:=1;
        my_uniimage_01.Name:='IMG_01_'+unimainmodule.ZVERTRAG.fieldbyname('STRUCTURE_NR').AsString;
        my_uniimage_01.Tag:=unimainmodule.ZVERTRAG.fieldbyname('STRUCTURE_NR').AsInteger;
       


        // A LABEL
        my_uniLabel_01:=TuniLabel.Create(my_uniPanel_01);
        my_uniLabel_01.Parent:=my_uniPanel_01;
        my_uniLabel_01.Left:=30;
        my_uniLabel_01.AutoSize:=false;
        my_uniLabel_01.Width:=270;
        my_uniLabel_01.Top:=3;
        my_uniLabel_01.Name:='LAB_01_'+unimainmodule.ZVERTRAG.fieldbyname('STRUCTURE_NR').AsString;
        my_uniLabel_01.Caption:=unimainmodule.ZVERTRAG.fieldbyname('OBJECT_NAME').AsString;
        my_uniLabel_01.Cursor:=crHandPoint;
        my_uniLabel_01.Font.Color:=text_rgb_01;
        my_uniLabel_01.Tag:=unimainmodule.ZVERTRAG.fieldbyname('STRUCTURE_NR').AsInteger;
                my_uniLabel_01.ClientEvents.UniEvents.Add
                ('OnAfterCreate=function OnAfterCreate(sender)'+
                ' {sender.cls="myUnselectable x-dbtext300-user"; }');




        // A BUTTON
        my_unibutton_01:=TUniButton.Create(self);
        my_unibutton_01.Parent:=my_uniPanel_01;
        my_unibutton_01.Width:=100;
        my_unibutton_01.Caption:='Eintrag löschen';
        my_unibutton_01.Name:='BTN_01_'+unimainmodule.ZVERTRAG.fieldbyname('STRUCTURE_NR').AsString;
        my_unibutton_01.Align:=alRight;
        my_unibutton_01.Visible:=true;
        my_unibutton_01.Tag:=unimainmodule.ZVERTRAG.fieldbyname('STRUCTURE_NR').AsInteger;
        my_unibutton_01.OnClick:=my_button_click_01;
                my_unibutton_01.ClientEvents.UniEvents.Add
                ('OnAfterCreate=function OnAfterCreate(sender)'+
                ' {sender.cls="hoverbutton"; }');


  // CALCULATE NEXT POSITION
  position_01:=position_01+hoehe_01;
  unimainmodule.ZVERTRAG.next;
end;// EOF




end;

 

Link to comment
Share on other sites

  • Administrators

Hello Farshad Mohajeri - very nice greetings from Austria :-)

 

the loop is 80 ... a small list ...

i hope - there is a way to increase the speed ..

 

Hello Erich,

 

80 is not small in this case.

Ext JS is not optimized for this kind of operations. As your list grows, dynamic insert operation will become slower and slower.

Link to comment
Share on other sites

Maybe you can decrease runtime creation by putting 80 hidden uniPanels on your form (with property Visible:=False or Left:=-4000...).
Then, in your loop, you just have to set the right properties of each uniPanel (using FindComponent method), without creating it first.  That's not a beautiful way but it can increase your performances.

 

You can also decrease loading time by avoiding "LoadFromFile" method for each image; maybe you can try to put your images in the resources of your application: the size of your .exe/.dll will increase, but loading time could be faster.

 

Finally, why not using LiveBindings instead of programmaticaly linking Captions, Texts and Names to your Tables ?

Link to comment
Share on other sites

hello Farshad,

 

i made the same with a UniHTMLFrame.. and it is (of course) very fast ..

 

 

my Phantasie 

is there a way for the future to create a especial simple "UniRuntimeContainer" with one uniRuntimePanel"?

 

"UniRuntimeContainer" with a DatasourceProperty and a "uniRuntimePanel"

in this uniRuntimePanel i drop  uniRuntimeLabel, uniRuntimeImage, uniRuntimeCheckbox and a uniRuntimeButton ....and so on..

this uniRuntimePanel will loop trough the database and makes copy of itselfe and the dropped components, since the EOF is reached ..

 

 

a cool property for this UniRuntimeContainer would be a  "spezialAlig" of the created uniRuntimePanels like "horizontal" or "vertical" 

 

Stringgrids, Imagegrids, Datagrids  and so one could be created very easy and would work very fast on clientside ...

 

 

Do you know the famouse "DBCtrlGrid" of Delphi7 ? 

 

 

var i       :Integer;
    s       :String;
    output  :String;
begin


UniHTMLFrame1.HTML.Clear;
UniHTMLFrame1.HTML.Append('<div>');


unimainmodule.ZVERTRAG.first;
while not unimainmodule.ZVERTRAG.Eof do
begin
   s:= unimainmodule.ZVERTRAG.fieldbyname('OBJECT_NAME').AsString;
   UniHTMLFrame1.HTML.Append('<p class="hoverpanel myUnselectable" onclick="ajaxRequest(data_vertragsverwaltung_vertrag.UniMemo1,''Panelclick'' , [ ''Parameter01=03'' , ''Parameter02=03'' ])";>'+s+'');
   UniHTMLFrame1.HTML.Append('<input class="x-btn hoverbutton myUnselectable" type="button" value="Delet test" onclick="ajaxRequest(data_vertragsverwaltung_vertrag.UniMemo1,''delete Record'' , [ ''Parameter01=93'' , ''Parameter02=93'' ])"; />');
   UniHTMLFrame1.HTML.Append('</p>');
   unimainmodule.ZVERTRAG.Next;
end;


UniHTMLFrame1.HTML.Append('</div>');




end;
Link to comment
Share on other sites

  • 3 months later...

Farshad, can you explain what happens every time I create a control at runtime in my current form, because I too have big speed problems when creating runtime edit controls for a database grid. Is there an ajax commnunication every time I create a new control, or why does it take so long?

 

Would it help to create them in an invisible form, and then set the parent to my current form once all the controls are created?

 

Is there any other trick?

Link to comment
Share on other sites

Farshad, can you explain what happens every time I create a control at runtime in my current form, because I too have big speed problems when creating runtime edit controls for a database grid. Is there an ajax commnunication every time I create a new control, or why does it take so long?

 

Would it help to create them in an invisible form, and then set the parent to my current form once all the controls are created?

 

Is there any other trick?

 

In fact, I just created about 100 controls in a hidden form before calling showmodal (3 secs), and I beat the creation of the SAME controls in the mainform by 300% (> 10 secs).

 

So what exactly is slowing down the control creation in the mainform? It really seems that every control creation is initiating some kind of communication - is this true?

 

That would imply that creating a large number of controls is better done in a hidden panel or form, and once done can be assigned to the parent form.

 

Good idea, or am I totally on the wrong theory?

Link to comment
Share on other sites

It really seems that every control creation is initiating some kind of communication - is this true?

No. The Client sends a request to the server, the server performs everything and sends the complete answer to Client.

 

The difference is if the server can create 1 complete html part so the client mus only insert this 1 part or if he must insert 100 small parts at different places.

 

Chrome, for example, has performance problems on deleting big parts.

Link to comment
Share on other sites

"Good idea, or am I totally on the wrong theory?"

 

That was exactly my suggestion (22th Nov 2013)...

Anyway, I cannot figure why you need to create 100 controls in runtime.  That is not a good practice, far from OOP, MVC and other design patterns.  Doing that with uniGUI is as odd as doing that with standard VCL or FMx forms.

Maybe you first need to think about the way you analyze/modelize/build your application, before trying to create so many controls...

Link to comment
Share on other sites

"Good idea, or am I totally on the wrong theory?"

 

That was exactly my suggestion (22th Nov 2013)...

Anyway, I cannot figure why you need to create 100 controls in runtime.  That is not a good practice, far from OOP, MVC and other design patterns.  Doing that with uniGUI is as odd as doing that with standard VCL or FMx forms.

Maybe you first need to think about the way you analyze/modelize/build your application, before trying to create so many controls...

 

No, your suggestion was creating the controls at design time. I created them at runtime in a hidden form, which accelerated the whole thing by 300% as explained above. I am just wondering why.

 

And concerning the design, it is well thought of: I have a grid, populated by an sql statement at runtime (and there can be infinite sql constructions on 90 existing tables of the database...), and beside the grid I dynamically show a vertical record editor. Every field has a title, an edit control and possibly a button. So if the query has 10 fields, that makes at least 20 controls created at runtime. Or would you rather I design an edit form for every possible joined sql statement containing any possible number of fields? ;-)

 

@ Oliver: does this mean that everytime I create a control at runtime, the server "inserts" this into the client. That would mean, that for 100 creations the server has to insert 100 times in the client, whereas if I create all controls in a hidden form at runtime, then set the parent of my panel (containing the controls) to mainform, then this "big insertion" is done only once?

Link to comment
Share on other sites

And concerning the design, it is well thought of: I have a grid, populated by an sql statement at runtime (and there can be infinite sql constructions on 90 existing tables of the database...), and beside the grid I dynamically show a vertical record editor. Every field has a title, an edit control and possibly a button. So if the query has 10 fields, that makes at least 20 controls created at runtime. Or would you rather I design an edit form for every possible joined sql statement containing any possible number of fields? ;-)

Well... If you don't see any other solution than create 100 controls at runtime or design edit forms for every possible joined sql statement, I think that you really need to think about the way you analyze/modelize your application...

For example: do your 100 fields need, for each one, titles, controls and button created and shown at the start of you application? Couldn't it be possible to show only 1 control and 1 button on the specific field you're mousing over?  In that case, you just need to create 1 button and 1 control, and show it over the field that your mouse is over...

 

Anyway, I don't think that the problem is about uniGUi performances, but about the way you want to make your application.

 

This article could interest you : https://www.sencha.com/blog/optimizing-ext-js-4-1-based-applications/.

 

Ex: in uniEvents of TUniPanel, you can set this function :

function beforeInit(sender)
{
   sender.xtype = 'container';
}

That will make your application faster if you use lot of TUniPanels.

Link to comment
Share on other sites

Well... If you don't see any other solution than create 100 controls at runtime or design edit forms for every possible joined sql statement, I think that you really need to think about the way you analyze/modelize your application...

For example: do your 100 fields need, for each one, titles, controls and button created and shown at the start of you application? Couldn't it be possible to show only 1 control and 1 button on the specific field you're mousing over?  In that case, you just need to create 1 button and 1 control, and show it over the field that your mouse is over...

 

Anyway, I don't think that the problem is about uniGUi performances, but about the way you want to make your application.

 

No, I think the problem is that I did not manage to make it clear to you what i am doing. Here's a screnshot with only 3 x 2 dynamically created fields:

filterPNG.png

 

"Current Record" is the panel with the dynamically created fields. The tables at the left are also dynamically populated from a mySQL database.

 

I don't want to offend you, but it might help to accept that there are project requirements you haven't though of, before repeatedly suggesting to change the design..:D That does not always help solve the problem.

 

But thank you for the Sencha tip - I will look into it.

Link to comment
Share on other sites

I think your "current record" view is better to implement via DBGrid and ClientDataSet with 2 fields being name and value, and utilize afterpost event to modify the needed fields. Or maybe something similar (UniStringGrid?), even UniHTMLFrame with dynamically created html table/divs/inputs and ajaxEvent callbacks would work much better.

ZigZig is right, you need to change the architecture of view model. Your app is not something special, the problem is that you approach it from a Delphi developer point of view, which would not always work in web no matter how awesome uniGUI is.

Link to comment
Share on other sites

@ Zilav: Thank you for your suggestions. But creating a handful of controls at runtime is Delphi standard, and if I cannot do it without large time delays or through complicated quirks, then - for me - what's the point of doing it in Delphi at all? I have close to 90 mySQL tables, and there are many other controls I need to create at runtime. In fact, basically, everything is created at runtime.

 

Your idea of using a stringgrid and manually populating it everytime a record changes is interesting (I've thought of it myself), but last resort for me - after all, I joined this forum because I like Delphi RAD and am not a fan of misusing controls for what they were not meant to. If there are good uniGUI data-aware controls, which connect perfectly to my TDataSource and TDataset, why complicate everything because there may be a pending speed problem with uniGUI, which may get solved soon. After all, I'm not the first person to notice this.

 

Anyhow, to get back to my observation, I removed the edit panel, put it in a hidden form, then parented it again after having it filled, and thus saved 7/10 of the time. I still have no explanation why this works so much faster, so if anyone can explain the technical background I (and I'm sure some others) would be grateful.

Link to comment
Share on other sites

@ Oliver: does this mean that everytime I create a control at runtime, the server "inserts" this into the client. That would mean, that for 100 creations the server has to insert 100 times in the client, whereas if I create all controls in a hidden form at runtime, then set the parent of my panel (containing the controls) to mainform, then this "big insertion" is done only once?

Link to comment
Share on other sites

I don't know how it works exactly in unigui, Farshad could say more on that...

 

But what must be done on the client? The client (browser) can only show HTML, so the new (visible) "controls" must be inserted as HTML code into the currrent HTML code using javascript on Client side. If there are 100, you must insert 100. But if this 100 are in a "container" you can produce HTML code for the complete Container and insert this (big) html part in one Operation.

 

Try to create a new Frame (TUniFrame) with the controls and then set .parent := form.

Link to comment
Share on other sites

Thank you Oliver, that's basically what I did and that explains it pretty well.

 

Maybe Farshad can comment on this and suggest a better way. Might be good idea to have some kind of Client.PaintLocked until all controls are created. I've been missing this for the uniDBGrid as well. Every action leads to a painting of the grid, but again, maybe I'm missing something else here.

Link to comment
Share on other sites

Maybe Farshad can comment on this and suggest a better way. Might be good idea to have some kind of Client.PaintLocked until all controls are created. I've been missing this for the uniDBGrid as well. Every action leads to a painting of the grid, but again, maybe I'm missing something else here.

 

Dear Michael,

 

It seems that you're not considering previous answers...

 

f you take a look at the topic about optimizing ExtJs (https://www.sencha.com/blog/optimizing-ext-js-4-1-based-applications/) as I suggested to you here, you will find answers to most of your questions.

 

For example : you can get something like "Client.PaintLocked" by doing this :

{
    Ext.suspendLayouts();
    // batch of updates
    Ext.resumeLayouts(true);
}

To avoid waste of time when filling grids, you have this trick :

  UniSession.JSCode(myGrid.JSName+'.store.suspendEvents();');

  //do something to myGrid
  

  UniSession.JSCode(mmyGrid.JSName+'.store.resumeEvents();');
  UniSession.JSCode(myGrid.JSName+'.view.refresh();'); 

(see also this topic : http://forums.unigui.com/index.php?/topic/3837-clear-stringgrid/?p=18367)

 

 

About Panels, you can decrease loading time with this trick :

function beforeInit(sender)
{
   sender.xtype = 'container';
}

(as I suggested here)

 

 

By the way, Farshad said that you could send a complete test case... and Zilav suggested that you use DBGrid and ClientDataSet with 2 fields being name and value, and utilize afterpost event to modify the needed fields.  

 

But I feel that you prefer to complain than try the solutions we offer you.

 

 

 

But creating a handful of controls at runtime is Delphi standard, and if I cannot do it without large time delays or through complicated quirks, then - for me - what's the point of doing it in Delphi at all?

 

 

Hum... I'm not sure that creating a handful of controls at runtime is Delphi standard... Anyway, a Web application is not a local PC application.  You must think about architecture, server tasks and client tasks, asynchronous communication with Ajax, etc.  Thinking that you can do the same thing with uniGUi (in a Web project) than with VCL (in a local application) is, imho, a huge mistake.  If you want to do so, I suggest you to try Intraweb or WebFMX (http://www.cybelesoft.com/webfmx/) : there you can build your application as a stand-alone executable and share it on the Internet.  But you cannot do that with uniGUI, that's not the purpose of this wonderful framework.

  • Upvote 2
Link to comment
Share on other sites

I dont know why this discussion about my project design is going on. And yes, creating controls at runtime in Delphi is a very common thing, and good practice or even necessary in many cases.

 

But I feel that you prefer to complain than try the solutions we offer you.

 

I found a solution myself without any Sencha tricks or misuse of components, posted it here to help others. I am not complaining about anything - all I wanted was to understand why my solution works and saves so much runtime. I am a Delphi programmer - I have no idea about how unGUI works (I have no source code), and I am not familiar with the extJS framework. Oliver was the only one who actually answered my question - everybody else seems to be complaing about my project design ;-)

 

@ ZigZag: thank you again, those are some helpful suggestions and I will look into them.

@ Farshad: I would love to send you a test case - I just don't have the time right now to extract the right lines of code from a 200.000 lines project. I hope maybe my observations together with others can help anyway.

  • Upvote 1
Link to comment
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
×
×
  • Create New...