IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Lazarus Pascal Discussion :

[0.9.31] StringGrid, filtre et optimisation [Lazarus]


Sujet :

Lazarus Pascal

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Invité
    Invité(e)
    Par défaut [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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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...
    Dernière modification par Invité ; 07/07/2011 à 08h55.

  2. #2
    Membre Expert

    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2009
    Messages
    935
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Aveyron (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2009
    Messages : 935
    Par défaut
    Salut,

    Je n'ai pas lu de docs a ce sujet, mais je me permet de faire des suppositions.
    La méthode 2 est lente car tu alloues de la mémoire 5000 fois en ajoutant une ligne a la fois. Il vaut mieux, je pense, ajouter plein de lignes au début, et en effacer si il y en a trop, comme ca, tu alloues seulement une fois de la mémoire.

    Par contre, la méthode 1, je ne sais pas comment l'expliquer ... Peut être que c'est dû à un rafraichissement du composant apres chaque RowHeight, et donc c'est lent ...

    En tout cas, la méthode 3 semble la meilleure et aussi la plus logique, bien que plus consommatrice de mémoire ...

  3. #3
    Membre émérite
    Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2010
    Messages
    469
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2010
    Messages : 469
    Par défaut
    Bonjour

    Et avec BeginUpdate et EndUpdate avant et après, qu'est ce que ça donne ?

  4. #4
    Invité
    Invité(e)
    Par défaut
    Bonjour Tintinux,

    Avec BeginUpdate... c'est sensationnel pour l'amélioration de la méthode 1
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    var
     Deb, Fin : TTime;
     i : integer;
    begin
     Deb := now();
     with sg1 do begin
       BeginUpdate;
       for i := 1 to RowCount -1 do
          if i mod 2 <> 0 then RowHeights[i] := 0;
       EndUpdate(True);
     end;
     Fin := now();
     Showmessage(TimeToStr(Fin-Deb)+' ( '+FloatTostr(Fin-Deb)+' )');
    end;
    --> 00:00:00 (~ 0,2 x 10^-7)

    Pour la méthode 2, le gain est moins sensible.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    var
     Deb, Fin : TTime;
     i, iRow : integer;
    begin
     Deb := now();
     iRow := 0;
     with sg1 do  begin
       sg2.BeginUpdate;
       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;
       sg2.EndUpdate(True);
     end;
     Fin := now();
     Showmessage(TimeToStr(Fin-Deb)+'('+FloatTostr(Fin-Deb)+')');
    end;
    --> 00:00:01 (~199 x 10^-7)

    Merci beaucoup. La méthode 1 me convient à beaucoup de titres. Reste cette incrémentation du Rowcount ligne par ligne. Mais c'est un autre problème.
    Cordialement. Gilles
    Dernière modification par Invité ; 07/07/2011 à 17h06.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [XL-2007] Optimisation d'un filtre avancé
    Par apt dans le forum Macros et VBA Excel
    Réponses: 18
    Dernier message: 24/07/2012, 16h25
  2. [XL-2007] Travaux sur filtre : optimisation de macro
    Par webisfun dans le forum Contribuez
    Réponses: 0
    Dernier message: 03/05/2012, 01h57
  3. Optimisation d'un filtre sur une table
    Par flyingfr53 dans le forum jQuery
    Réponses: 5
    Dernier message: 27/07/2011, 20h47
  4. [numpy] optimiser un filtre pour 2 arrays
    Par josmiley dans le forum Calcul scientifique
    Réponses: 4
    Dernier message: 09/09/2010, 23h22
  5. Optimisation algo filtre médian
    Par TheCreech dans le forum Traitement d'images
    Réponses: 4
    Dernier message: 07/01/2010, 17h01

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo