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

Langage Delphi Discussion :

Des techniques d'optimisation du code


Sujet :

Langage Delphi

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    210
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 210
    Points : 84
    Points
    84
    Par défaut Des techniques d'optimisation du code
    Bonjour,

    je lance un poste pour reporter toutes les techniques d'optimisation du code en Delphi. C'est a dire tous les trucs et astuces qui peuvent augmenter la vitesse d'execution d'un programme. Par exemple: creer une liste avant la boucle for et non apres..

  2. #2
    Membre chevronné
    Avatar de Clorish
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 474
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 474
    Points : 2 158
    Points
    2 158
    Par défaut
    L'idee est bonne sur le papier .. mais j'ai peur que ce post devienne rapidement illisible ....
    le fait que chacun a sa propre vision combiné a la multitude d'idees et astuces qui existent ... le debat risuqe d'etre long .... et de partir dans tous les sens
    On passe du temps a vous repondre, alors soyez sympas, passez du temps ..... a vous relire !
    --
    Pourquoi tant de haine pour cette pauvre aide Delphi ????
    Aiiimezzz laaaaa .... Si-Non-Cham-Pi-Gnon !!!
    --
    Pour plus de Renseignements : Venez me rejoindre sur Msn .... Promis je mords pas

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    210
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 210
    Points : 84
    Points
    84
    Par défaut
    disons alors les astuces basiques qui prennent peu de place et qui sont tres utiles a savoir, que l'on rencontre tous les jours quoi. Les "trucs" indispensables a savoir..

  4. #4
    Membre chevronné
    Avatar de Clorish
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 474
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 474
    Points : 2 158
    Points
    2 158
    Par défaut
    J'invite donc les autres membre a jouer le jeu et a ne pas contredire les propositions sauf si cela s'avere strictement necessaire, afin de concerver une certaine lisibilitée .....


    Bon ben je commence par en citer 2 ou 3 :

    - Tests Securisés :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    If 3 = a Then ShowMEssage('a = 3');
    Cette habitude de codage evite la meprise suivante :
    dans les lagage basie sur la syntaxe "C", confondant affectation et test
    Tres pratique quand on passe d'un language a l'autre (C, C++, Java, php => Delphi)

    - Case indexté par des chaines :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    Lst := TStringList.Create;
    Lst.add('toto');
    Lst.add('titi');
    Lst.add('tutu');
    Case Lst.IndexOf(S) do
      0 : ShowMEssage('toto');
      1 : ShowMEssage('titi');
      2 : ShowMEssage('tutu');
      End;
    - Clarté de codage des IF :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Begin
    [...]
    If Not Valide Then Exit;
    <Code si Valide=True>
    End;
    au lieu de :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    Begin
    [...]
    If Valide Then
      Begin
      <Code si Valide=True>
      End;
    End;
    (Avis Strictement Personnel)
    On passe du temps a vous repondre, alors soyez sympas, passez du temps ..... a vous relire !
    --
    Pourquoi tant de haine pour cette pauvre aide Delphi ????
    Aiiimezzz laaaaa .... Si-Non-Cham-Pi-Gnon !!!
    --
    Pour plus de Renseignements : Venez me rejoindre sur Msn .... Promis je mords pas

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    210
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 210
    Points : 84
    Points
    84
    Par défaut
    j'ai pas compris le 1er

  6. #6
    Membre chevronné
    Avatar de Clorish
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 474
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 474
    Points : 2 158
    Points
    2 158
    Par défaut
    Citation Envoyé par Art19
    j'ai pas compris le 1er
    Le principe est simple.
    En Delphi le "=" est signe d'egalité.
    En C-like programes, c'est signe d'affectation et une instruction renvoie le resultat de l'affectation.

    Donc Quand on change de langages constement, on fait des erreurs du genre :
    Qui a pour effet d'affecter "3" a la variable a et retourne comme resultat 3
    donc ca revient a ecrire :
    3 >=0 donc equivalent a False. ET le test est toujours faux (ou toujours vrai selon la valeur affecter et renvoyée).

    Pour eviter ce probleme, inverser le teste permet de generer une erreur en C-like langages (lvalue non affectable) car on ne peut affecter "a" dans "3" .....
    Cette technique permet de corriger rapidement l'erreur de sasie sans avoir a passer un bon paquet d'heures (jours ?) a chercher d'ou cela peut il venir .....

    J'en ai fait les frais
    On passe du temps a vous repondre, alors soyez sympas, passez du temps ..... a vous relire !
    --
    Pourquoi tant de haine pour cette pauvre aide Delphi ????
    Aiiimezzz laaaaa .... Si-Non-Cham-Pi-Gnon !!!
    --
    Pour plus de Renseignements : Venez me rejoindre sur Msn .... Promis je mords pas

  7. #7
    Membre régulier Avatar de Dirk-Pitt
    Inscrit en
    Juillet 2007
    Messages
    71
    Détails du profil
    Informations personnelles :
    Âge : 63

    Informations forums :
    Inscription : Juillet 2007
    Messages : 71
    Points : 81
    Points
    81
    Par défaut
    Une question bête, ceci a t'il un impact sur l'optimisation du code ? Et en ce qui nous concerne en Delphi ?

  8. #8
    Membre éprouvé
    Avatar de CapJack
    Homme Profil pro
    Prof, développeur amateur vaguement éclairé...
    Inscrit en
    Mars 2004
    Messages
    624
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Prof, développeur amateur vaguement éclairé...
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2004
    Messages : 624
    Points : 988
    Points
    988
    Par défaut
    Ce n'est pas pour contredire, mais pour signaler un hors-sujet : Dirk-Pitt demande des méthodes pour optimiser la vitesse d'exécution, pas pour améliorer la portabilité ou faciliter le travail en équipe... l'indexation par chaînes, par exemple, est complètement à l'opposé de la question posée, me semble-t-il.

    Sur l'optimisation du code en vitesse d'exécution, il faut savoir que le compilateur optimise déjà grandement le code compilé, mais que son comportement est largement configurable : tu peux déjà regarder du côté des directives de compilation. Attention toutefois, une directive qui accélère l'exécution a souvent des effets de bord non souhaitables.

    Toujours réfléchir à l'algorithme utilisé : par exemple si mon logiciel a souvent besoin de rechercher une information dans un tableau, que l'information à rechercher soit de préférence triée pour pouvoir utiliser un algorithme par dichotomie en O(log n).

    Eviter autant que faire se peut les appels multiples à des boucles, en utilisant toujours une variable temporaire pour stocker une valeur longue à calculer et qui sert plusieurs fois. Par exemple, si CalculeNombre est une fonction qui calcule un nombre d'éléments, et qui consomme du temps :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    // Mauvais : deux appels à la même fonction
    if CalculNombre > 0
     then for I := 1 to CalculeNombre do...
     
    // Bon
    N := CalculeNombre;
    if N > 0 then for I := 1 to N do
    Ce serait le cas pour StrLen par exemple : pour les chaînes AZT, la longueur est évaluée par une boucle, très rapide certes, mais quand même...

  9. #9
    Membre éclairé Avatar de PadawanDuDelphi
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2006
    Messages
    678
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : Bâtiment

    Informations forums :
    Inscription : Août 2006
    Messages : 678
    Points : 717
    Points
    717
    Par défaut
    Salut,

    En règle général, pour augmenter la vitesse de calcul tu va être obligé d'augmenter ton nombre de lignes de code (en gros optimistaion de ton code est inversement proportionnel à l'optimisation de la vitesse de calcul).

    A+.
    For crying out loud !

  10. #10
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    624
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 624
    Points : 754
    Points
    754
    Par défaut
    on peut ajouter aussi la déclaration des chaines en const dans les prototypes de routines afin d'éviter une copie locale + un bloc "try finally" caché.

    Bucknall a écrit un livre qui traite des algorithmes et des structures de données(sous l'angle de la performance, rapidité) en Delphi (tableau, files, listes, piles, algo de recherche de tri, tables de hachage, arbres binaires, machines à etat, compression de données etc...).

    un exemple d'optimisation:
    Algo d'ordre O(n):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    function CountBits1V1(B : byte) : byte;
    begin
      Result := 0;
      while (B<>0) do begin
        if Odd(B) then
        inc(Result);
        B := B shr 1;
      end;
    end;
    Le précalcule des valeurs dans un tableau statique évite l'usage d'une boucle.(8 cycles de division)

    Algo d'ordre O(1): (10 fois plus rapide)
    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
    const
    BitCounts : array [0..255] of byte =
    (0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, // de 0000 0000 à 0000 1111 pour la 1ère ligne
    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
    4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8);
    end;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    function CountBits1V2(B : byte) : byte;
    begin
      Result := BitCounts[B];
    end;
    @+

  11. #11
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 263
    Points
    3 263
    Par défaut Optimisation de la rapidité lors de manipulations de StrngList's
    Bonjour,

    Lors de la manipulations de StringList's on a souvent tendance d'utiliser, dans un premier temps, les méthodes-standard dont certaines mangent plus de nettement plus de temps que d'autres du fait que l'obtention du résultat nécessite de décaler vers l'avant ou vers l'arrière de la liste les cases qui contiennent les chaines et l'object associé qui leur est associé.

    Il est clair que maListe.Delete(i) nécessite de décaler vers l'avant la liste à partir de i jusqu'à la fin et que maListe.Insert(i,chaine) doit d'abord décaler la suite vers l'arrière avant d'insérer la chaîne et son object en question dans les bonnes cases ... et c'est pareil lorsque l'on permute des lignes lors d'un tri ou pour une autre raison.
    S'ajoutent souvent aux temps d'exécution les conséquences d'un choix inappropré de la valeur de la propriété Sorted.

    Comme les deux méthodes les plus rapides sont maListe.add(chaine) et maListe.addObject(chaine,objet) lorsque Sorted:=FALSE l'ajout se fait illico-presto en fin de liste sans nécessiter aucun décalage, en conséquence l'astuce consiste à utiliser ces deux fonctions pour éviter, notamment à l'intérieur d'une boucle, l'emploi des fonctions plus gourmandes en temps.
    (il est évident que s'il sagit d'un appel unique à Delete(i) ou à Insert() on peut les utiliser directement)

    Et pour éviter l'emploi de ces méthodes gourmandes en temps il est souvent plus rapide de céer une nouvelle liste modifiée à partir de la liste existante.

    Exemple de scénario à réaliser :
    Etape 1 : On charge une liste de chaînes classées dans un ordre chronologique confirmé par Sorted=False (rapide, les ajouts s'effectuant directement en fin de liste)
    Etape 2 : On veut trier la liste dans l'ordre Alpha croissant : on utilise la méthode Sort en attendant de trouver plus rapide.
    Etape 3 : On veut rétablir l'ordre chronologique de l'étape 1, sans permuter les lignes de la structure.

    Solution optimisée :

    Pour l'étape 2 :
    2.1 : Avant de trier dans l'orde Alpha on crée à partir de la liste chargée une nouvelle liste dans laquelle on place l'indice-de-l'ordre-initial dans l'object associé à chaque chaine en utilisant AddObject() : il faut 0,6 millisec pour une liste de 2000 mots courants (Pentium III 1,13 GHz)
    2.2 : On trie la même liste avec la méthode standard Sort : 16 ms soit 27 fois plus lent que pour la création de liste de l'étape 2.1

    Pour l'étape 3 : A partir de la liste triée on crée une nouvelle liste en deux temps :
    3.1 : la structure de la nouvelle liste avec Sorted:=False, est d'abord intialisée avec une boucle de Add('')
    3.1 : dans la boucle suivante on affecte à la ligne correspondant à l'indice-de-l'ordre-initial-mémorisé la chaine sitée à l'indice de boucle et on retrouve ainsi l'ordre initial d'avant le tri sans avoir utilisé ni Delete() ni Insert() : pour l'ensemble de l'étape 3 : mis 0,85 ms soit 19 fois plus rapide que la méthode standard Sort.

    Code pour l'étape 2.1 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    function  CreerListeAvecIndicesEnObjet(const LSOrdreIni : TStringList) : TStringList;
    var       ind : integer; // s : string;
    begin     Result:=TStringList.create;
              Result.Sorted:=false;
              for ind:=0 to LSOrdreIni.count-1
               do Result.AddObject(LSOrdreIni[ind],tObject(integer(ind)));
    end;
    Code pour l'étape 3 :
    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
    20
     
    function  RetablirOrdreInitial(const ListeSourceInd : TStringList) : TStringList;
    //        Pour ListeSourceInd qui contient dans ses Objects les indices-de-l'ordre-initial
    //        Renvoie une liste rétablie dans son ordre initial
    var       i,indMemorise : integer;
    begin     Result:=TStringList.create;
              Result.Sorted:=False;
              for i:=0 to ListeSourceInd.count-1 do
              begin // initialisation nouvelle liste et en même temps on met rien en object
                    // pour virer éventuellement les objects en virant la liste-source après l'appel
                    Result.Add('');
              end;
              for i:=0 to ListeSourceInd.count-1 do
              begin // on place dans les chaines '' le mot correspondant à l'indice-initial
                    // mémorisé dans l'object
                    indMemorise:=integer(ListeSourceInd.Objects[i]);
                    Result[indMemorise]:=ListeSourceInd[i];
                    // on pourrait ici mettre de nouveau l''indice dans l'object si nécessaire
              end;
    end;
    De la même façon que la function RetablirOrdreInitial() évite l'emploi de Delete() et de Insert() on peut créer à partir d'elle une fonction tout aussi rapide qui crée une liste triée dans l'ordre inverse de celui obtenu par Sort ... et en mémorisant les indices-de-l'ordre-initial au bon moment dans les objects des listes on peut ainsi basculer rapidement d'un classement en ordre croissant à un classement en ordre décroissant.

    Pour ce qui est des méthodes-standard maListe.Find() et maListe.IndexOf() se souvenir que leur vitesse maximale est obtenue lorsque la liste est non seulement triée mais que sa propriété Sorted:=TRUE car la méthode Sort ne bascule pas automatiquement cette propriété à true si elle a été appelée après un Sorted:=false. (en tous cas pas sous Delphi-5)

    A+
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

Discussions similaires

  1. optimisation du code pour des combobox
    Par oscar.cesar dans le forum Macros et VBA Excel
    Réponses: 12
    Dernier message: 08/03/2008, 13h30
  2. [PHP-JS] Optimisation du code avec des boucles
    Par jiojioforever dans le forum Langage
    Réponses: 3
    Dernier message: 15/06/2007, 16h02
  3. [optimisation de code] des conseils ?
    Par Lady dans le forum Langage
    Réponses: 7
    Dernier message: 07/05/2007, 10h08
  4. Réponses: 8
    Dernier message: 14/09/2006, 16h43
  5. Optimisation du code des ordres SQL
    Par Titouf dans le forum Langage SQL
    Réponses: 1
    Dernier message: 14/08/2005, 22h08

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