Page 1 of 2 1 2 LastLast
Results 1 to 15 of 25

Thread: TGridPanel.Free ?? Slow

  1. #1

    TGridPanel.Free ?? Slow

    Hoi,

    Is er een mogelijkheid om dat hele FREE te versnellen?
    Een matrix van 6x6 is wel te doen maar 26x26 kost veel tijd en dat zit in de FREE.

    Code:
    for I := 0 to Pred(MainGridPanel.ControlCount) do
        MainGridPanel.Controls[0].Free; // Always slow
    Hier is de complete INIT.

    Code:
    procedure TfrmControlPad.CreateGradientPanels(const rowCount, colCount: Integer);
    var
      I: Integer;
      AMainPanel: TPanel;
      AMainLabel: TLabel;
      AMainGradient: TGradient;
    begin
      MainGridPanel.RowCollection.BeginUpdate;
      MainGridPanel.ColumnCollection.BeginUpdate;
    
      for I := 0 to Pred(MainGridPanel.ControlCount) do
        MainGridPanel.Controls[0].Free; // Always slow
    
      // Cannot clear if there are controls, so first remove "old" controls above
      MainGridPanel.RowCollection.Clear;
      MainGridPanel.ColumnCollection.Clear;
    
      for I := 1 to rowCount do MainGridPanel.RowCollection.Add;
      for I := 1 to colCount do MainGridPanel.ColumnCollection.Add;
    
      for I := 0 to Pred(rowCount * colCount) do
      begin
        // Background Panel
        AMainPanel := TPanel.Create(Self);
        AMainPanel.Parent := MainGridPanel; //magic: place in the next empty cell
        AMainPanel.StyleElements := [];
        AMainPanel.Visible := True;
        AMainPanel.Tag := (I + 1);
        AMainPanel.Name := 'Panel' + Format('%.2d', [I + 1]);
        AMainPanel.BevelOuter := bvNone;
        AMainPanel.ParentBackground := False;
        AMainPanel.ParentColor := True;
        AMainPanel.ShowCaption := False;
        AMainPanel.Align := alClient;
        AMainPanel.AlignWithMargins := True;
        AMainPanel.Margins.SetBounds(0, 0, 2, 2);
        // Label on Panel
        AMainLabel := TLabel.Create(Self);
        AMainLabel.Parent := AMainPanel;
        AMainLabel.StyleElements := [];
        AMainLabel.ParentFont := False;
        AMainLabel.ParentColor := False;
        AMainLabel.WordWrap := True;
        AMainLabel.Top := ControlpadHintTop;
        AMainLabel.Left := ControlpadHintLeft;
        AMainLabel.Font.Size := ControlpadFontsize;
        AMainLabel.Font.Color := clBlack;
        AMainLabel.Visible := True;
        AMainLabel.Tag := (I + 1);
        AMainLabel.Name := 'Label' + Format('%.2d', [I + 1]);
        AMainLabel.Transparent := True;
        // Gradient on Panel
        AMainGradient := TGradient.Create(Self);
        AMainGradient.Parent := AMainPanel;
        AMainGradient.StyleElements := [];
        AMainGradient.Visible := True;
        AMainGradient.Tag := (I + 1);
        AMainGradient.Name := 'Gradient' + Format('%.2d', [I + 1]);
      end;
    
      MainGridPanel.RowCollection.EndUpdate;
      MainGridPanel.ColumnCollection.EndUpdate;
    end;
    En voor de liefhebbers met ssPercentage problemen. Dit werkt heel goed ik gebruik het al jaren...
    En zo ook voor de Colomns

    Code:
    procedure SetGridResizeRows;
      var
       I, ADiv, AMod: Integer;
       AValue: Double;
      begin 
        ADiv := (MainGridPanel.Height ) div rowCount;
        AMod := (MainGridPanel.Height) mod rowCount;
    
        MainGridPanel.RowCollection.BeginUpdate;
    
        { Kolommen berekenen }
        for I := 0 to Pred(MainGridPanel.RowCollection.Count) do
        begin
          MainGridPanel.RowCollection[I].SizeStyle := ssAbsolute;
          MainGridPanel.RowCollection[I].Value := ADiv;
        end;
    
        { Fix restant; AMod pixel verdelen over de eerste kolommen }
        for I := 0 to Pred(AMod) do
        begin
          if (I < MainGridPanel.RowCollection.Count) then // Controle voor AV!
          begin
            AValue := MainGridPanel.RowCollection[I].Value;
            MainGridPanel.RowCollection[I].SizeStyle := ssAbsolute;
            MainGridPanel.RowCollection[I].Value := (AValue + 1);
          end;
        end;
    
        MainGridPanel.RowCollection.EndUpdate;
      end;
    Last edited by DragonFly; 14-Jul-21 at 13:12.

  2. #2
    Code:
    for I := 0 to Pred(MainGridPanel.ControlCount) do
        MainGridPanel.Controls[0].Free; // Always slow
    Waarom blijf je Controls[0] vrijmaken?
    Ik zie de loop voor 'I' niet werkelijk gebruikt worden.

  3. #3
    Senior Member
    Join Date
    Aug 2004
    Location
    Rotterdam
    Posts
    150
    Quote Originally Posted by MaartenW View Post
    Code:
    for I := 0 to Pred(MainGridPanel.ControlCount) do
        MainGridPanel.Controls[0].Free; // Always slow
    Waarom blijf je Controls[0] vrijmaken?
    Ik zie de loop voor 'I' niet werkelijk gebruikt worden.
    Als je I wel gebruikt moet je de for-loop achterstevoren doorlopen (for i := Pred(Count) downto 0.
    Anders krijg je een acces violation, denk er maar eens over na.

  4. #4
    Fornicatorus Formicidae VideoRipper's Avatar
    Join Date
    Mar 2005
    Location
    Vicus Saltus Orientalem
    Posts
    5,703
    Ik denk dat Maarten dat wel snapt, maar dat het gebruik van een variabele zinloos is als je er niets mee doet.
    Doe dan dit (al vind ik dat ook vrij vies):
    Delphi Code:
    1. while MainGridPanel.ControlCount  > 0 do
    2.   MainGridPanel.Controls[0].Free;

    Het liefst wil je het oplossen van achteren naar voren:
    Delphi Code:
    1. for I := Pred(MainGridPanel.ControlCount) downto 0 do
    2.   MainGridPanel.Controls[I].Free;
    Het is niet voor niets dat de lijst begint bij 0 en eindigt bij Count - 1: iedere keer als je de eerste in de rij vrijgeeft, schuiven alle items erna een plek op (n - 1) en dat kost ook tijd (al weet ik niet hoeveel, maar het kost wel onnodig tijd)
    TMemoryLeak.Create(Nil);

  5. #5
    Technisch klopt het met Free(0) want 0 blijft. Wordt intern geregeld.
    Achterste voren is zelfde traagheid.
    Vandaar de vraag is er een snellere manier?

  6. #6
    Senior Member
    Join Date
    Aug 2004
    Location
    Rotterdam
    Posts
    150
    Waarin ben je dit aan het testen? Delphi?

  7. #7
    Het werkt inderdaad wel, want als je de eerste vrijgeeft, wordt de tweede de eerste. Controls is een collection waarbij alles opschuift.

    Van achter naar voor zou sneller zijn, omdat er intern minder met arrays geschoven moet worden. Toch is dat maar van minimaal belang in dit geval. Een array van 26x26 pointers is niet zo spannend.

    Het grootste issue is dat je daadwerkelijk controls aan het vrijgegeven bent, wat een hele berg messages naar de omliggende controls veroorzaakt, verschuivingen, re-alignments, met repaints en alles erbij.

    Een goede aanvulling is:

    Delphi Code:
    1. MainGridPanel.DisableAlign; // Helemaal aan het begin van de init
    2. MainGridPanel.EnableAlign; // Helemaal aan het eind
    Intern wordt dit ook gedaan per control dat je vrijgeeft, maar deze methods (net als BeginUpdate, overigens) werken met een soort tellertje. Als dat tellerje na EneableAlign/EndUpdate op 0 staat, worden alsnog al die alignments uitgevoerd. Het interne gebruik van die method heeft daardoor weinig effect op de totale performance van je loop: je zit nog steeds ongeveer 1500 (?) keer de alignments van de controls binnen het panel te valideren. Door dit zelf aan het begin van de method te doen, net zoals voor de row en column collections, breng je dat terug naar 1 keer.

    Dat maakt niet alleen het vrijgeven, maar ook het maken van nieuwe controls een stuk sneller. Op mijn PC ongeveer 7 keer zo snel.

    Het lijkt erop dat je de tijd dan nog een keer kan halveren door het hele control tijdens de init Invisible te maken. Wellicht de moeite waard om te kijken hoe dat komt. Blijkbaar gebeurt er toch nog iets grafisch...

    Geen idee overigens waarom dit een gridpanel moet zijn. Met alleen een label en een gradient, lijkt het erop dat je het ook zelf zou kunnen tekenen in een bitmap/op een TCustomControl. Zo lang je geen daadwerkelijke cellen met keyboard focus nodig hebt, is dat waarschijnlijk net zo makkelijk en een stuk sneller.
    Last edited by GolezTrol; 14-Jul-21 at 18:22.
    1+1=b

  8. #8
    Nee ook buiten de debug. Gaat om 26x 26 Grid traag. Maar goed neem mij tip mee dan heb je perfecte indeling.
    Niet gaan nadenken want probleem is echt FREE zoals geschreven.

  9. #9
    MainGridPanel.DisableAlign; nog niet geprobeerd.
    Is dan MainGridPanel.RowCollection.BeginUpdate; niet aan de orde?

  10. #10
    Quote Originally Posted by DragonFly View Post
    Is dan MainGridPanel.RowCollection.BeginUpdate; niet aan de orde?
    Alleen voor het updaten van de rowcollection zelf. Dat staat los van alle controls in de cellen van het grid, zou ik denken, maar het precieze effect weet ik niet.
    Veel kwaad zal het sowieso niet doen, en het lijkt iets te schelen, maar niet zoveel als DisableAlign.
    Last edited by GolezTrol; 14-Jul-21 at 18:33.
    1+1=b

  11. #11
    Als je het niet onzichtbaar maakt, dan kan je nog deze regel helemaal aan het eind van de loop plaatsen, dus net na het maken van de gradient.

    Delphi Code:
    1. AMainPanel.Parent := MainGridPanel; //magic: place in the next empty cell

    Daardoor krijgt het grid maar 1 redraw, i.p.v. 2 extra als het label en gradient op het panel geplaatst worden. Scheelt toch ook weer een goeie 10%.
    1+1=b

  12. #12
    Luister beste vriend het zit in de FREE en alles wat daarna komt is super snel.
    Maar ga het morgen even testen.

  13. #13
    Fornicatorus Formicidae VideoRipper's Avatar
    Join Date
    Mar 2005
    Location
    Vicus Saltus Orientalem
    Posts
    5,703
    Dat klopt, gewaardeerde vriend, maar de oorzaak ligt hem in het opruimen (dat doet .Free) van de/het/een object.

    Wat GolezTrol (en anderen hier) aangeven, is dat je de tijd die het opruimen kost kunt versnellen door zaken als hertekenen (zij het wellicht met een omweg) te voorkomen.
    TMemoryLeak.Create(Nil);

  14. #14
    Alright vrienden Het zal per PC verschillen welk deel snel of traag is.

    Of het is maar schijn. Het lijkt bij mij alsof er lang niets gebeurt en daarna snel de nieuwe controls komen, maar dat is niet waar.
    Het maken van de controls duurt zelf lang, wat je daarna ziet is alleen het tekenen van de reeds gemaakte controls.

    In totaal duurt de hele init ongeveer 8 seconden bij mij, waarvan ongeveer 1 seconde voor het vrijgeven van de bestaande controls (bij een tweede aanroep, de eerste keer is de lijst leeg en is het heel snel).
    Met de diverse tips gaat het geheel terug naar 1,5 en met het tijdelijk verbergen van het gridpanel zelfs naar 0,8.

    Ik heb System.Diagnostics.TStopWatch gebruikt om verschillende onderdelen te testen. Baseer je niet alleen op wat je ziet gebeuren op het scherm, want dat vertekent, en suggereert dat het vrijgeven van de oude controls en opbouwen van de rows en column veel meer tijd kost dan daadwerkelijk het geval is.
    1+1=b

  15. #15
    Aanmaken van de Controls in mijn voorbeeld is super snel. Natuurlijk een breakpoint gezet.
    Als de lijst leeg is gaat het snel maar 26x26 is enorm.
    Ik ga morgen op onderzoek. Straks thuis.
    Nogmaals het is de Free die het doet. zie dan wel elk element opeens weg gaan In de Grid. Viisueel
    ???

Page 1 of 2 1 2 LastLast

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •