From 50ac0f66a12c11f13e6fc87570d89ab8876e5e92 Mon Sep 17 00:00:00 2001 From: mattias Date: Sun, 18 Oct 2015 12:46:19 +0000 Subject: [PATCH] IDE: added cache for FindFileInAllPackages, patch #28871 from Ondrej git-svn-id: trunk@50096 - --- ide/main.pp | 21 ++---- packager/packagesystem.pas | 130 ++++++++++++++++++++++++++++++++++--- packager/pkgmanager.pas | 11 +--- 3 files changed, 129 insertions(+), 33 deletions(-) diff --git a/ide/main.pp b/ide/main.pp index ce9f275701..9988df39d0 100644 --- a/ide/main.pp +++ b/ide/main.pp @@ -387,8 +387,6 @@ type procedure mnuChgBuildModeClicked(Sender: TObject); procedure ToolBarOptionsClick(Sender: TObject); - private - FLastUnitInfoFileName: string; // used in UpdateProjectMenu private fBuilder: TLazarusBuilder; function DoBuildLazarusSub(Flags: TBuildLazarusFlags): TModalResult; @@ -3714,22 +3712,17 @@ begin GetCurrentUnit(ASrcEdit,AUnitInfo); if Assigned(AUnitInfo) then begin - if (AUnitInfo.Filename <> FLastUnitInfoFileName) then - begin - PkgFile:=PackageGraph.FindFileInAllPackages(AUnitInfo.Filename,true, - not AUnitInfo.IsPartOfProject); - CanOpenPkgOfFile:=Assigned(PkgFile); - CanAddCurFile:=(not AUnitInfo.IsVirtual) and FileExistsUTF8(AUnitInfo.Filename) - and not AUnitInfo.IsPartOfProject; - MainIDEBar.itmPkgOpenPackageOfCurUnit.Enabled:=CanOpenPkgOfFile; - MainIDEBar.itmPkgAddCurFileToPkg.Enabled:=CanAddCurFile; - FLastUnitInfoFileName := AUnitInfo.Filename; - end; + PkgFile:=PackageGraph.FindFileInAllPackages(AUnitInfo.Filename,true, + not AUnitInfo.IsPartOfProject); + CanOpenPkgOfFile:=Assigned(PkgFile); + CanAddCurFile:=(not AUnitInfo.IsVirtual) and FileExistsUTF8(AUnitInfo.Filename) + and not AUnitInfo.IsPartOfProject; + MainIDEBar.itmPkgOpenPackageOfCurUnit.Enabled:=CanOpenPkgOfFile; + MainIDEBar.itmPkgAddCurFileToPkg.Enabled:=CanAddCurFile; end else begin MainIDEBar.itmPkgOpenPackageOfCurUnit.Enabled:=False; MainIDEBar.itmPkgAddCurFileToPkg.Enabled:=False; - FLastUnitInfoFileName := ''; end; end; diff --git a/packager/packagesystem.pas b/packager/packagesystem.pas index bd9c907c2d..25483f025a 100644 --- a/packager/packagesystem.pas +++ b/packager/packagesystem.pas @@ -144,6 +144,33 @@ type ErrorMessage: string; end; + TLazPackageGraph = class; + + { TLazPackageGraphFileCachePackageInfo } + + TLazPackageGraphFileCachePackageInfo = record + FileName: string; + ChangeStamp: Integer; + end; + + { TLazPackageGraphFileCache } + + TLazPackageGraphFileCache = class(TObject) + private + FGraph: TLazPackageGraph; + FPackageInfo: array of TLazPackageGraphFileCachePackageInfo; + FFilesList: TFilenameToPointerTree; + FRemovedFilesList: TFilenameToPointerTree; + function NeedsUpdate: Boolean; + procedure Update; + public + constructor Create(AOwner: TLazPackageGraph); + destructor Destroy; override; + public + function FindFileInAllPackages(TheFilename: string; + IgnoreDeleted, FindVirtualFile: boolean): TPkgFile; + end; + { TLazPackageGraph } TLazPackageGraph = class @@ -182,6 +209,7 @@ type FTree: TAVLTree; // sorted tree of TLazPackage FUpdateLock: integer; FVerbosity: TPkgVerbosityFlags; + FFindFileCache: TLazPackageGraphFileCache; function CreateDefaultPackage: TLazPackage; function GetCount: Integer; function GetPackages(Index: integer): TLazPackage; @@ -632,6 +660,93 @@ begin Result:=UTF8Trim(Result,[]); end; +{ TLazPackageGraphFileCache } + +constructor TLazPackageGraphFileCache.Create(AOwner: TLazPackageGraph); +begin + inherited Create; + + FGraph := AOwner; + SetLength(FPackageInfo, 0); + FFilesList := TFilenameToPointerTree.Create(true); + FRemovedFilesList := TFilenameToPointerTree.Create(true); +end; + +destructor TLazPackageGraphFileCache.Destroy; +begin + SetLength(FPackageInfo, 0); + FreeAndNil(FFilesList); + FreeAndNil(FRemovedFilesList); + + inherited Destroy; +end; + +function TLazPackageGraphFileCache.FindFileInAllPackages( + TheFilename: string; IgnoreDeleted, FindVirtualFile: boolean): TPkgFile; + + procedure FindFileInStrList(const Files: TFilenameToPointerTree); + begin + Result:=TPkgFile(Files[TheFilename]); + if (Result<>nil) and (not FindVirtualFile) + and (not FilenameIsAbsolute(Result.Filename)) then + Result := nil; + end; + +begin + Result:=nil; + + if NeedsUpdate then + Update; + + FindFileInStrList(FFilesList); + if Result<>nil then Exit; + if not IgnoreDeleted then + FindFileInStrList(FRemovedFilesList); +end; + +function TLazPackageGraphFileCache.NeedsUpdate: Boolean; +var + I: Integer; +begin + if FGraph.Count <> Length(FPackageInfo) then + Exit(True); + + for I := 0 to FGraph.Count-1 do + if (FPackageInfo[I].ChangeStamp <> FGraph[I].ChangeStamp) + or (FPackageInfo[I].FileName<>FGraph[I].Filename) + then + Exit(True); + + Result := False; +end; + +procedure TLazPackageGraphFileCache.Update; +var + I, L: Integer; + xPck: TLazPackage; +begin + SetLength(FPackageInfo, FGraph.Count); + FFilesList.Clear; + FRemovedFilesList.Clear; + for I := 0 to FGraph.Count-1 do + begin + xPck := FGraph[I]; + FPackageInfo[I].ChangeStamp := xPck.ChangeStamp; + FPackageInfo[I].FileName := xPck.Filename; + + for L := 0 to xPck.FileCount-1 do + begin + FFilesList[xPck.Files[L].GetFullFilename]:=xPck.Files[L]; + FFilesList[xPck.Files[L].Filename]:=xPck.Files[L]; + end; + for L := 0 to xPck.RemovedFilesCount-1 do + begin + FRemovedFilesList[xPck.RemovedFiles[L].GetFullFilename]:=xPck.RemovedFiles[L]; + FRemovedFilesList[xPck.RemovedFiles[L].Filename]:=xPck.RemovedFiles[L]; + end; + end; +end; + { TLazPkgGraphBuildItem } // inline @@ -925,6 +1040,7 @@ begin FreeAndNil(FLazarusBasePackages); FreeAndNil(FItems); FreeAndNil(FTree); + FreeAndNil(FFindFileCache); inherited Destroy; end; @@ -1477,17 +1593,11 @@ end; function TLazPackageGraph.FindFileInAllPackages(const TheFilename: string; IgnoreDeleted, FindVirtualFile: boolean): TPkgFile; -var - Cnt: Integer; - i: Integer; begin - Cnt:=Count; - for i:=0 to Cnt-1 do begin - Result:=Packages[i].FindPkgFile(TheFilename,IgnoreDeleted, - FindVirtualFile); - if Result<>nil then exit; - end; - Result:=nil; + if FFindFileCache=nil then + FFindFileCache := TLazPackageGraphFileCache.Create(Self); + + Result := FFindFileCache.FindFileInAllPackages(TheFilename, IgnoreDeleted, FindVirtualFile); end; procedure TLazPackageGraph.FindPossibleOwnersOfUnit(const TheFilename: string; diff --git a/packager/pkgmanager.pas b/packager/pkgmanager.pas index 02616d201e..45551c0fda 100644 --- a/packager/pkgmanager.pas +++ b/packager/pkgmanager.pas @@ -4922,7 +4922,6 @@ end; function TPkgManager.SearchFile(const AFilename: string; SearchFlags: TSearchIDEFileFlags; InObject: TObject): TPkgFile; var - i: Integer; APackage: TLazPackage; CurFilename: String; begin @@ -4934,14 +4933,8 @@ begin if Result<>nil then exit; end; if not (siffDoNotCheckAllPackages in SearchFlags) then begin - for i:=0 to PackageGraph.Count-1 do begin - APackage:=PackageGraph[i]; - CurFilename:=AFilename; - APackage.ShortenFilename(CurFilename,true); - Result:=APackage.SearchShortFilename(CurFilename,SearchFlags); - //debugln(['TPkgManager.SearchFile Pkg=',APackage.Filename,' CurFilename="',CurFilename,'" Resul=',Result<>nil,' HasDirectory=',APackage.HasDirectory,' ExpFile=',APackage.DirectoryExpanded]); - if Result<>nil then exit; - end; + Result := PackageGraph.FindFileInAllPackages(AFilename, True, True); + if Result<>nil then exit; end; Result:=nil; end;