erich.wanker Posted November 21, 2013 Posted November 21, 2013 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; Quote
Administrators Farshad Mohajeri Posted November 21, 2013 Administrators Posted November 21, 2013 while not unimainmodule.ZVERTRAG.Eof do How many times does above loop iterate? Quote
erich.wanker Posted November 22, 2013 Author Posted November 22, 2013 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 .. Quote
Administrators Farshad Mohajeri Posted November 22, 2013 Administrators Posted November 22, 2013 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. Quote
Administrators Farshad Mohajeri Posted November 22, 2013 Administrators Posted November 22, 2013 That said, you may send us a complete test case to see if some optimizations can be done in this field. Quote
ZigZig Posted November 22, 2013 Posted November 22, 2013 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 ? Quote
erich.wanker Posted November 22, 2013 Author Posted November 22, 2013 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; Quote
misc Posted March 19, 2014 Posted March 19, 2014 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? Quote
wrt54gs Posted March 19, 2014 Posted March 19, 2014 The design problem. If 80 loops, then create 80 buttons & Labels................... Quote
misc Posted March 19, 2014 Posted March 19, 2014 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? Quote
Oliver Morsch Posted March 19, 2014 Posted March 19, 2014 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. Quote
ZigZig Posted March 19, 2014 Posted March 19, 2014 "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... Quote
misc Posted March 19, 2014 Posted March 19, 2014 "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? Quote
ZigZig Posted March 19, 2014 Posted March 19, 2014 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. Quote
misc Posted March 19, 2014 Posted March 19, 2014 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: "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.. That does not always help solve the problem. But thank you for the Sencha tip - I will look into it. Quote
zilav Posted March 20, 2014 Posted March 20, 2014 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. Quote
Administrators Farshad Mohajeri Posted March 20, 2014 Administrators Posted March 20, 2014 That said, you may send us a complete test case to see if some optimizations can be done in this field. Quote
misc Posted March 20, 2014 Posted March 20, 2014 @ 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. Quote
misc Posted March 20, 2014 Posted March 20, 2014 @ 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? Quote
Oliver Morsch Posted March 20, 2014 Posted March 20, 2014 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. Quote
misc Posted March 21, 2014 Posted March 21, 2014 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. Quote
Administrators Farshad Mohajeri Posted March 21, 2014 Administrators Posted March 21, 2014 That said, you may send us a complete test case to see if some optimizations can be done in this field. 1 Quote
ZigZig Posted March 21, 2014 Posted March 21, 2014 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. 2 Quote
misc Posted March 21, 2014 Posted March 21, 2014 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. 1 Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.