[0.9.31] StringGrid, filtre et optimisation
	
	
		Bonsoir,
J'ai déjà partiellement abordé le sujet dans une autre discussion, mais je trouve le fonctionnement des StringGrids extrêmement lent... et j'essaye de le comprendre pour optimiser.
Je cherchais la meilleure méthode pour filtrer "visuellement" une StringGrid et d'une manière plus large pour les utiliser au mieux. Comme j'ai déjà rencontré récemment  un problème de lenteur sur les tris de ce composant, j'ai fait quelques tests.
La StringGrid de référence que j'ai utilisée est une StringGrid par défaut modifiée ainsi :
	Code:
	
1 2 3 4 5 6 7 8 9 10 11 12 13 14
   | var
   Deb, Fin : TTime;
   sTmp : string;
   i : integer;
begin
 Deb := now();
 with SG1 do begin
   RowCount := 10000;
   for i:=1 to 9999 do
    Cells[1,i] := intToStr(i);
 end;
 Fin := now();
 Showmessage(TimeToStr(Fin-Deb)+' ( '+FloatTostr(Fin-Deb)+' )');
end; | 
 --> 00:00:00 (~4 x 10^-7)
J'ai utilisé 3 méthodes pour filtrer "visuellement" les nombres pairs.
Méthode 1 : Je parcours la SG1 et cache les lignes impaires :
	Code:
	
1 2 3 4 5 6 7 8 9 10 11
   | var
 Deb, Fin : TTime;
 i : integer;
begin
 Deb := now();
 with sg1 do 
   for i := 1 to RowCount -1 do
      if i mod 2 <> 0 then RowHeights[i] := 0;
 Fin := now();
 Showmessage(TimeToStr(Fin-Deb)+' ( '+FloatTostr(Fin-Deb)+' )');
end; | 
 --> 00:00:03 (~441 x 10^-7). Et à l'utilisation, c'est en effet très "perceptible"...
Méthode 2: Je parcours SG1 et place les lignes paires dans une SG2 dont les propriétés sont définies par défaut dans l'IDE.
	Code:
	
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
   | var
 Deb, Fin : TTime;
 i, iRow : integer;
begin
 Deb := now();
 iRow := 0;
 with sg1 do
   for i := 1 to RowCount -1 do
      if i mod 2 = 0 then begin
       iRow := iRow+1;
       sg2.RowCount := iRow +1;
       sg2.cells[1,iRow] := cells[1,i];
      end;
 Fin := now();
 Showmessage(TimeToStr(Fin-Deb)+'('+FloatTostr(Fin-Deb)+')');
end; | 
  --> 00:00:03 (~462 x 10^-7)
Troisème méthode, identique à la seconde mais programmée différemment : le RowCount de SG2 n'est pas modifié 5000 fois mais défini une fois avant le traitement.
	Code:
	
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
   | var
 Deb, Fin : TTime;
 iRow, i : integer;
begin
 Deb := now();
 sg2.RowCount := 5000;
 iRow := 0;
 with sg1 do
   for i := 1 to RowCount -1 do
      if i mod 2 = 0 then begin
       iRow := iRow+1;
       sg2.cells[1,iRow] := cells[1,i];
      end;
 Fin := now();
 Showmessage(TimeToStr(Fin-Deb)+' ( '+FloatTostr(Fin-Deb)+' )');
 end; | 
 --> 00:00:00 (~2 x 10^-7)
Si je peux éventuellement expliquer la différence  entre la méthode 3 et la méthode 2 (la modification du RowCount donc l'ajout d'une ligne semble extrêmement lent*), pourquoi la méthode 1 est-elle si lente ? Entre les 2 méthodes également lentes et la plus rapide, il y a un facteur 200. Même si éventuellement on peut considérer que ce facteur n'est pas "significatif" et reste finalement acceptable, l'attente de l'utilisateur du résultat du filtre est désagréable... et donc s'il est possible de l'optimiser...
Bref, si vous avez de la documentation sur l'optimisation des StringGrids, je suis preneur... Cela m'évitera -même si c'est très intéressant et formateur- de m'engager dans des méthodes peu performantes.
Cordialement. Gilles
Rq : le code suivant est équivalent à la méthode 2
	Code:
	
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
   | var
 Deb, Fin : TTime;
 i : integer;
begin
 Deb := now();
 sg2.RowCount := 1;
 with sg1 do
   for i := 1 to RowCount -1 do
      if i mod 2 = 0 then begin
       sg2.RowCount := sg2.RowCount +1;
       sg2.cells[1,sg2.RowCount -1] := cells[1,i];
      end;
 Fin := now();
 Showmessage(TimeToStr(Fin-Deb)+'('+FloatTostr(Fin-Deb)+')');
end; | 
 --> 00:00:03 (~458 x 10^-7). C'est donc la permière utilisation de sg2.RowCount à chaque itération de la boucle qui ralentit le processus. Ensuite sa réutilisation, mémorisée, ne pénalise plus...