Bert-Jan 1 Posted November 30, 2020 (edited) Hi all, In the last few months I build an app for iOS and Android which expanded rapidly due to customer requests. It is basically one unit with one main tabcontrol. Most tabItems have tabcontrols in them up to three levels. So many forms with many objects like rectangles, buttons and listboxes. Lately the IDE became very slow and crashed frequently. Today, after adding a new tabItem and saving and closing the project, the whole project does not open again. I believe it is too heavy now. My question is: what can I do to keep the IDE afloat and still expand the project? Are there any best practices to develop a large multi device app? My Windows 10 PC has 64 GB memory. Edited November 30, 2020 by Bert-Jan Share this post Link to post
Anders Melander 1783 Posted November 30, 2020 Without knowing anything about your architecture I would say that you need to move the content of each of the tabs into individual frames and then create and destroy these frames on-demand. 1 Share this post Link to post
Guest Posted November 30, 2020 (edited) 2 hours ago, Bert-Jan said: Hi all, ... My Windows 10 PC has 64 GB memory. Good Anders, "On-Demand" is my favorite approach when it comes to visual components! I think that the biggest problem of "our dear" IDE is the inheritance of the online analysis of the language itself, that is, "if the type is not in agreement, then, from now on, everything will also not be"! Even now with the "LSP" protocol in greater use! This time, everything is evaluated in real time, and, in the case of visual components, the thing gets even more terrible, because, in addition to the type, we still have the resources consumed by the components themselves, mainly the visual (graphical) part. In terms of "On-Demand", we still have the type analysis, however, the graphic resources are not being loaded yet. Therefore, one less weight to carry the project. To decrease the load a little, you could have everything that is graphically shown, that is, that is repeated in many forms, you could save in templates, for example, using "Frames", or even the inheritance of forms, which could have less impact on the project load. Not to mention that, if there are open connections to services, external or not, such as the Database, this also contributes to increase the load on the IDE. I have a test project, where I use a "TFrame" (unit uMyFrameModel1.pas) to populate a "TGridPanel" (in unit uFormMainExec.pas), and, the frame containing its components, "On-Demand" are created only at the right time! So, a lot already helps in the process of loading as a whole! // a Frame is like a TForm, then... *of course, no at all! ... lFrame := TfrmMyFrameModel1.Create( grdpnlOnTheForm ); // The Killer! ... // for last, when all it's ready: lFrame.Parent := grdpnlOnTheForm; ... But of course, I don't know how to scale your problem! It's just my speculation. I don't know if I was clear to try to analyze the issue? Sorry !!! hug Edited November 30, 2020 by Guest Share this post Link to post
Bert-Jan 1 Posted December 1, 2020 Thank you both. Does this mean I have to create the components programmatically? Share this post Link to post
mvanrijnen 123 Posted December 1, 2020 (edited) [badmorning mode] Yes the Delphi IDE performs at is best as: - You create all components manually - Do not use form/frame inherentance - Disable all code- and error insight features. - Use external compiler it's Embarcadero's believe that the IDE is best used as a luxury notepad. (but then you better use notepad++) 🙂 but hey, what else you gonna do with the few thousand dollars of the cost of Delphi 🙂 [/badmorning mode] Edited December 1, 2020 by mvanrijnen 1 Share this post Link to post
Lars Fosdal 1792 Posted December 1, 2020 Design-time live data components can be real killers as well. Share this post Link to post
Guest Posted December 1, 2020 11 hours ago, Bert-Jan said: Thank you both. Does this mean I have to create the components programmatically? As your project is already committed, I think it's time to review some steps ... so, in order not to lose all the work, I would create a new project, and, little by little, I would add the units and evaluate where the bottleneck really begins. .. understood? But maximum, you will lose a few hours, and, for free, gain some new way of seeing things. That is, this is a learning experience, not a curse! Share this post Link to post
Anders Melander 1783 Posted December 1, 2020 11 hours ago, Bert-Jan said: Does this mean I have to create the components programmatically? Yes. I usually use a simple factory pattern. It briefly goes like this (view = frame): Create a "view registry" class. This class wraps a dictionaly that maps between a view interface and a class type. Move all your stuff into frames. For each frame assign them an interface and register the interface and the view class in the view registry. Create a "view manager" class. This class wraps a TDictionary<TGUID, TView> that contains the currently active view instances and is also responsible for creating new views. So something like: View (i.e. frame) abstract base class and API: unit Foo.Views.API; interface type IView = interface ['{4057A1F4-F22C-4CCF-89DE-9F4AE2E790DE}'] procedure Initialize; end; type // Abstract base class of your views. TView = class abstract(TFrame, IView) protected // IView procedure Initialize; virtual; end; TViewClass = class of TView; type IViewRegistry = interface ['{B4EC0F81-24DF-41D9-BF8A-CE0D9958C9A9}'] procedure RegisterView(const GUID: TGUID; ViewClass: TViewClass); procedure UnregisterView(const GUID: TGUID); function FindView(const GUID: TGUID): TViewClass; end; type IViewManager = interface ['{B4EC0F81-24DF-41D9-BF8A-CE0D9958C9A9}'] function OpenView(const GUID: TGUID): IView; procedure CloseView(const GUID: TGUID); function FindView(const GUID: TGUID): IView; end; implementation ... end. The API of a single view: unit Foo.Views.MyView.API; interface type IMyView = interface ['{063646E3-FB0D-4B8C-984A-A5E54F543651}'] procedure FooBar; end; implementation end. The implementation of a single view: unit Foo.Views.MyView; interface uses Foo.Views.API, Foo.Views.MyView.API; type // Trick to get the IDE to behave without registering the frame in a package TFrame = TView; TMyView = class(TFrame, IMyView) protected // IView procedure Initialize; override; // IMyView procedure FooBar; end; implementation ... intialization // Register our implementation of the IMyView interface ViewRegistry.RegisterView(IMyView, TMyView); end; and then you "just" have to Implement IViewRegistry and IViewManager unit Foo.Views.Manager; interface uses Foo.Views.API; function ViewRegistry: IViewRegistry; function ViewManager: IViewManager; implementation type TViewRegistry = class(TInterfacedObject, IViewRegistry) private FRegistry: TDictionary<TGUID, TViewClass>; protected // IViewRegistry procedure RegisterView(const GUID: TGUID; ViewClass: TViewClass); procedure UnregisterView(const GUID: TGUID); function FindView(const GUID: TGUID): TViewClass; end; var FViewRegistry: TViewRegistry; function ViewRegistry: IViewRegistry; begin if (FViewRegistry = nil) then FViewRegistry := TViewRegistry.Create Result := FViewRegistry; end; procedure TViewRegistry.RegisterView(const GUID: TGUID; ViewClass: TViewClass); begin FRegistry.Add(GUID, ViewClass); end; procedure TViewRegistry.UnregisterView(const GUID: TGUID); begin FRegistry.Remove(GUID, ViewClass); end; function TViewRegistry.FindView(const GUID: TGUID): TViewClass; begin if (not FRegistry.TryGetValue(GUID, Result)) then Result := nil; end; type TViewManager = class(TInterfacedObject, IViewManager) private FViews: TDictionary<TGUID, IView>; protected // IViewManager function OpenView(const GUID: TGUID): IView; procedure CloseView(const GUID: TGUID); function FindView(const GUID: TGUID): IView; end; function TViewManager.OpenView(const GUID: TGUID): IView; begin if (FViews.TryGetValue(GUID, Result) then Exit; var ViewClass := ViewRegistry.FindView(GUID); if (ViewClass = nil) then Boom! Result := ViewClass.Create; FViews.Add(Result); Result.Initialize; end; ...etc. etc... end. 1 1 Share this post Link to post
Bert-Jan 1 Posted December 1, 2020 It seems I've got some homework. Thank you all. Share this post Link to post
Guest Posted December 1, 2020 1 hour ago, Bert-Jan said: It seems I've got some homework. Be advised, that in some countries, during these times, working any other way is currently prohibited and may incur hefty fines. Share this post Link to post
Guest Posted December 2, 2020 (edited) 4 hours ago, Dany Marmur said: Be advised, that in some countries, during these times, working any other way is currently prohibited and may incur hefty fines. How would be for Amsterdan-Girls from De Wallen? Edited December 2, 2020 by Guest Share this post Link to post
Bert-Jan 1 Posted December 2, 2020 10 hours ago, Dany Marmur said: Be advised, that in some countries, during these times, working any other way is currently prohibited and may incur hefty fines. True. I always work at home. For more than 15 years now. Share this post Link to post