From 4e15bdcd15535eaecc4637b41e394548e3cb1c71 Mon Sep 17 00:00:00 2001 From: Basile Burg Date: Tue, 9 Dec 2014 04:54:51 +0100 Subject: [PATCH] optimized entities-connection performances at startup --- lazproj/coedit.lpi | 2 +- lazproj/coedit.lpr | 4 +-- src/ce_cdbcmd.pas | 3 --- src/ce_editor.pas | 1 - src/ce_messages.pas | 1 - src/ce_observer.pas | 55 +++++++++++++++++++++++++++++++-------- src/ce_projconf.pas | 1 - src/ce_projinspect.pas | 1 - src/ce_search.pas | 1 - src/ce_staticexplorer.pas | 5 ++-- src/ce_staticmacro.pas | 1 - src/ce_widget.pas | 1 - 12 files changed, 49 insertions(+), 27 deletions(-) diff --git a/lazproj/coedit.lpi b/lazproj/coedit.lpi index 1ead881a..0e8bb7a1 100644 --- a/lazproj/coedit.lpi +++ b/lazproj/coedit.lpi @@ -296,7 +296,7 @@ - + diff --git a/lazproj/coedit.lpr b/lazproj/coedit.lpr index 3a8625f4..a0bdab2c 100644 --- a/lazproj/coedit.lpr +++ b/lazproj/coedit.lpr @@ -6,8 +6,8 @@ uses {$IFDEF UNIX}{$IFDEF UseCThreads} cthreads, {$ENDIF}{$ENDIF} - Interfaces, Forms, lazcontrols, runtimetypeinfocontrols, ce_libman, ce_tools, - ce_dcd, ce_observer, ce_main, ce_writableComponent, ce_options, ce_symstring, + Interfaces, Forms, lazcontrols, runtimetypeinfocontrols, ce_observer, ce_libman, + ce_tools, ce_dcd, ce_main, ce_writableComponent, ce_options, ce_symstring, ce_staticmacro; {$R *.res} diff --git a/src/ce_cdbcmd.pas b/src/ce_cdbcmd.pas index 79ed9b92..65af9e94 100644 --- a/src/ce_cdbcmd.pas +++ b/src/ce_cdbcmd.pas @@ -55,10 +55,7 @@ begin inherited; Enabled := exeInSysPath('cdb'); if Enabled then - begin EntitiesConnector.addObserver(self); - EntitiesConnector.endUpdate; - end; end; destructor TCECdbWidget.destroy; diff --git a/src/ce_editor.pas b/src/ce_editor.pas index a67b1226..dea831b2 100644 --- a/src/ce_editor.pas +++ b/src/ce_editor.pas @@ -90,7 +90,6 @@ begin end; // EntitiesConnector.addObserver(self); - EntitiesConnector.endUpdate; end; destructor TCEEditorWidget.destroy; diff --git a/src/ce_messages.pas b/src/ce_messages.pas index e04bd2d8..2157c502 100644 --- a/src/ce_messages.pas +++ b/src/ce_messages.pas @@ -152,7 +152,6 @@ begin btnClearCat.OnClick := @actClearCurCatExecute; // EntitiesConnector.addObserver(self); - EntitiesConnector.endUpdate; end; destructor TCEMessagesWidget.destroy; diff --git a/src/ce_observer.pas b/src/ce_observer.pas index 0ba19b56..d993d41e 100644 --- a/src/ce_observer.pas +++ b/src/ce_observer.pas @@ -16,18 +16,26 @@ type private fObservers: TObjectList; fSubjects: TObjectList; - fUpdating: boolean; + fUpdatesCount: Integer; + procedure tryUpdate; procedure updateEntities; + function getIsUpdating: boolean; public constructor create; destructor destroy; override; - // + // forces the update, fixes begin/add pair error or if immediate update is needed. + procedure forceUpdate; + // entities will be added in bulk, must be followed by an enUpdate(). procedure beginUpdate; + // entities has ben added in bulk procedure endUpdate; + // add/remove entities, update is automatic procedure addObserver(anObserver: TObject); procedure addSubject(aSubject: TObject); procedure removeObserver(anObserver: TObject); procedure removeSubject(aSubject: TObject); + // should be tested before forceUpdate() + property isUpdating: boolean read getIsUpdating; end; (** @@ -71,6 +79,9 @@ var implementation +uses + LCLProc; + {$REGION TCEEntitiesConnector --------------------------------------------------} constructor TCEEntitiesConnector.create; begin @@ -85,11 +96,33 @@ begin inherited; end; +function TCEEntitiesConnector.getIsUpdating: boolean; +begin + exit(fUpdatesCount > 0); +end; + +procedure TCEEntitiesConnector.tryUpdate; +begin + {$IFDEF DEBUG} + if fUpdatesCount > 0 then + DebugLn('saved uselless update in TCEEntitiesConnector') + else + DebugLn('efficient update in TCEEntitiesConnector'); + {$ENDIF} + if fUpdatesCount <= 0 then + updateEntities; +end; + +procedure TCEEntitiesConnector.forceUpdate; +begin + updateEntities; +end; + procedure TCEEntitiesConnector.updateEntities; var i,j: Integer; begin - fUpdating := false; + fUpdatesCount := 0; for i := 0 to fSubjects.Count-1 do begin if not (fSubjects[i] is ICESubject) then @@ -104,20 +137,21 @@ end; procedure TCEEntitiesConnector.beginUpdate; begin - fUpdating := true; + fUpdatesCount += 1; end; procedure TCEEntitiesConnector.endUpdate; begin - updateEntities; + fUpdatesCount -= 1; + tryUpdate; end; procedure TCEEntitiesConnector.addObserver(anObserver: TObject); begin if fObservers.IndexOf(anObserver) <> -1 then exit; - fUpdating := true; fObservers.Add(anObserver); + tryUpdate; end; procedure TCEEntitiesConnector.addSubject(aSubject: TObject); @@ -126,25 +160,25 @@ begin exit; if fSubjects.IndexOf(aSubject) <> -1 then exit; - fUpdating := true; fSubjects.Add(aSubject); + tryUpdate; end; procedure TCEEntitiesConnector.removeObserver(anObserver: TObject); var i: Integer; begin - fUpdating := true; fObservers.Remove(anObserver); for i := 0 to fSubjects.Count-1 do if fSubjects[i] <> nil then (fSubjects[i] as ICESubject).removeObserver(anObserver); + tryUpdate; end; procedure TCEEntitiesConnector.removeSubject(aSubject: TObject); begin - fUpdating := true; fSubjects.Remove(aSubject); + tryUpdate; end; {$ENDREGION} @@ -153,13 +187,11 @@ constructor TCECustomSubject.create; begin fObservers := TObjectList.create(false); EntitiesConnector.addSubject(Self); - EntitiesConnector.endUpdate; end; destructor TCECustomSubject.destroy; begin EntitiesConnector.removeSubject(Self); - EntitiesConnector.endUpdate; fObservers.Free; Inherited; end; @@ -200,6 +232,7 @@ end; initialization EntitiesConnector := TCEEntitiesConnector.create; + EntitiesConnector.beginUpdate; finalization EntitiesConnector.Free; EntitiesConnector := nil; diff --git a/src/ce_projconf.pas b/src/ce_projconf.pas index 0c9b0cdc..ef299bf6 100644 --- a/src/ce_projconf.pas +++ b/src/ce_projconf.pas @@ -53,7 +53,6 @@ begin Grid.OnEditorFilter := @GridFilter; // EntitiesConnector.addObserver(self); - EntitiesConnector.endUpdate; end; destructor TCEProjectConfigurationWidget.destroy; diff --git a/src/ce_projinspect.pas b/src/ce_projinspect.pas index 7c5eb6e8..38969517 100644 --- a/src/ce_projinspect.pas +++ b/src/ce_projinspect.pas @@ -83,7 +83,6 @@ begin Tree.PopupMenu := contextMenu; // EntitiesConnector.addObserver(self); - EntitiesConnector.endUpdate; end; destructor TCEProjectInspectWidget.destroy; diff --git a/src/ce_search.pas b/src/ce_search.pas index 1c75df37..15c790ea 100644 --- a/src/ce_search.pas +++ b/src/ce_search.pas @@ -92,7 +92,6 @@ begin fReplaceMru:= TMruList.Create; // EntitiesConnector.addObserver(self); - EntitiesConnector.endUpdate; end; destructor TCESearchWidget.Destroy; diff --git a/src/ce_staticexplorer.pas b/src/ce_staticexplorer.pas index 20fd9fd5..7d116dd6 100644 --- a/src/ce_staticexplorer.pas +++ b/src/ce_staticexplorer.pas @@ -86,7 +86,7 @@ type implementation {$R *.lfm} -uses ce_libman, ce_symstring; +uses LCLProc, ce_libman, ce_symstring; {$REGION Standard Comp/Obj------------------------------------------------------} constructor TCEStaticExplorerWidget.create(aOwner: TComponent); @@ -138,7 +138,6 @@ begin Tree.PopupMenu := contextMenu; // EntitiesConnector.addObserver(self); - EntitiesConnector.endUpdate; end; destructor TCEStaticExplorerWidget.destroy; @@ -513,7 +512,7 @@ begin if ndCat = nil then begin {$IFDEF DEBUG} - writeln(memb.Items[i].GetPath('kind').AsString); + DebugLn(memb.Items[i].GetPath('kind').AsString); {$ENDIF} continue; end; diff --git a/src/ce_staticmacro.pas b/src/ce_staticmacro.pas index a1f498c7..46eb10b3 100644 --- a/src/ce_staticmacro.pas +++ b/src/ce_staticmacro.pas @@ -89,7 +89,6 @@ begin updateCompletor; // EntitiesConnector.addObserver(Self); - EntitiesConnector.endUpdate; end; destructor TCEStaticEditorMacro.destroy; diff --git a/src/ce_widget.pas b/src/ce_widget.pas index 17224b60..3d74fd89 100644 --- a/src/ce_widget.pas +++ b/src/ce_widget.pas @@ -128,7 +128,6 @@ begin PopupMenu := contextMenu; EntitiesConnector.addObserver(self); - EntitiesConnector.endUpdate; end; destructor TCEWidget.destroy;