begin process at 2012 02 16 09:00:27
  Trouver un code source :
 
dans
 
Accueil > 

Tutoriels

 > 

Optimisation du code

 > OPTIMISATION D'ALGORITHME

OPTIMISATION D'ALGORITHME


 Information sur le tutoriel

Note :
8,8 / 10 - par 5 personnes
8,80 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

 Description

Il s'agit d'un tableau comparatif de différentes fonctions du Framework.Net et de quelques observations en découlant permettant d'améliorer significativement le temps d'exécution de vos algorithmes...

Tutorial


Bonjour à tous !
J'ai réalisé une petite étude sur le temps d'exécution de plusieurs fonctions très utilisées du .Net, voici tout d'abord la manière dont j'ai procédé pour mes mesures :

    Sub Main()

        Process.GetCurrentProcess.PriorityClass = ProcessPriorityClass.RealTime

        Dim w AsNew System.Diagnostics.Stopwatch

        w.Start()

        Test()

        w.Stop()

        System.Windows.Forms.Clipboard.SetText(Replace(Format(w.ElapsedTicks / 1000000 - 0.009556, "0.000000"), ",", "."))

    End Sub

 

    Sub Test()

        Dim i AsInteger, a As'Type retourné par la fonction à tester

        For i = 0 To 1000000

            a = 'Fonction à tester

        Next

    End Sub


Vous remarquerez sans doute que j'effectue 1 000 000 de fois la fonction et que je divise le résultat obtenu par 1 000 000 afin de minimiser l'erreur de mesure, et que je soustrait 0.009556 à mon résultat final, ceci étant la tare mesurée, correspondant à l'instruction Next et à l'incrémentation du i.
Voici mon tableau de mesure :

 

Fonctions

Ticks

Notes

Strings

 

 

For - Next

0.009556

Boucle For vide, simplement pour avoir la tare de mes mesures

Len(s)

0.012670

Où s est un String de 10 caractères. Même temps avec 10000.

s.Length

0.005127

Où s est un String de 10 caractères. Même temps avec 10000.

Mid(s, 2, 3)

0.274652

Où s est un String de 10 caractères. Même temps avec 10000.

s.Substring(2, 3)

0.265801

Où s est un String de 10 caractères. Même temps avec 10000.

Replace(s, " ", "a")

10.683268

Où s est un String = Space(10) (-> 10 remplacements).

Replace(s, " ", "a")

5.889826

Où s est un String = Space(5) (-> 5 remplacements).

Replace(s, "b", "a")

1.839295

Où s est un String = Space(10) (-> 0 remplacements).

Replace(s, "b", "a")

1.506057

Où s est un String = Space(5) (-> 0 remplacements).

Instr(s, "b")

1.046385

Où s est un String = « aaaaaaaaaaaaaaaabaaaa ».

s.Contains("b")

1.107969

Où s est un String = « aaaaaaaaaaaaaaaabaaaa ».

s.Contains("bbbbbbbbb")

0.940577

Où s est un String = « aaaaaabbbbbbbbbaaaa ».

s.Insert(4, "yyy")

0.934973

Où s est un String = Space(10).

s.Insert(4, "yyy")

7.735215

Où s est un String = Space(1000).

s.Remove(2, 10)

0.929358

Où s est un String = Space(40).

s.Substring(0, 2) & s.Substring(12, 28)

1.183333

Où s est un String = Space(40). Renvoie la même chose que la précédente, juste pour illustrer l'importance de la précision de la fonction choisie.

s.StartsWith("abc")

1.617434

Où s est un String = 'abc' & Space(10).

(InStr(s, "abc") = 1)

0.694170

Même chose que le précédent, beaucoup plus rapide !

s.EndsWith("abs")

1.172057

Où s est un S = Space(10) & 'abc'

(InStr(s, "abc") = s.Length - 3)

0.920107

Même chose que le précédent, beaucoup plus rapide !

(InStr(s, "abc") = s.Length - "abc".Length)

0.991431

Toujours plus rapide même si la longueur de la chaine est inconnue

 

 

 

Calculs

 

 

b + c

0.004991

b et c as integer

b + c

0.004884

b et c as double

b + c

0.006764

b as double et c as integer

b + c

0.169333

b as double et c as integer mais conversion implicite du résultat -> integer

Int(b + c)

0.726987

b as double et c as integer (Ne pas utiliser Int() pour convertir !)

b + c

0.220982

b et c as double mais conversion implicite du résultat -> integer

b + c

0.015684

b et c as Int16  (Remarquez que c'est plus long que sur les integers !)

b + c

0.003586

b et c as Int32  (Presque le même temps qu'avec des integers.)

b + c

0.011505

b et c as Int64

b + c

0.008947

b et c as Long  (Nettement plus rapide qu'avec les Int64 !)

sin(b)

0.225270

b as double

cos(b)

0.248604

b as double

sqrt(b)

0.066458

b as double

tan(b)

0.285205

b as double

pow(b, 20.0)

0.423138

b as double

b ^ 20

0.426442

b as double

max(b, c)

0.016820

b as integer, c as integer

If b > c Then a = b Else a = c

0.010731

b as integer, c as integer

min(b, c)

0.017247

b as integer, c as integer

If b < c Then a = b Else a = c

0.009976

b as integer, c as integer

sqrt(b ^ 2 + c ^ 2)

1.314850

b as double, c as double (Fonction distance, b = x1 - x2, c = y1 - y2)

b ^ 2 + c ^ 2

1.233296

b as double, c as double (Fonction distance utilisable pour comparaison, faible avantage)

b

0.003946

b as double (Simple assignement)

b ^ 2

0.481059

b as double

b * b

0.004273

b as double (Ho my god !!!!)

b * b + c * c

0.005938

b as double, c as double (Fonction distance utilisable pour comparaison, énorme avantage)

sqrt(b * b + c * c)

0.045453

b as double, c as double (Voilà comment il faut la faire la fonction distance !!!)

 

 

 

Tableaux

 

 

b 0->10 (c 0->10 (a = tab(b, c)))

4.236800

tab(10, 10) as integer  (b 0->10(.) signifie For b = 0 to 10 (.) Next)

b 0->121 (a = tab(b))

1.794521

tab(121) as integer  (Quand c'est possible privilégiez une seule dimension !)

b 0->10 (c 0->10 (a = tab(b * 10 + c)))

3.420987

tab(121) as integer  (Avec transformation depuis 2 dimensions)

 

 

 

b 0->100 (a = tab(b))

1.795740

tab(100) as integer

b 0->100 (a = tab(b))

2.985771

tab as new list(of integer) - Initialisées avec 101 éléments, préférez les tableaux !

tab(50)

0.121390

tab(100) as double, juste pour illustrer la lenteur d'une assignation (Cfr B48)

 

De manière assez clair, on peut en ressortir les améliorations potentielles suivantes :

-         Remplacer Len(s) par s.Length lorsqu'il s'agit de texte bien sûr

-         Utiliser les fonctions String.Remove et String.Insert plutôt que des String.Substring ou Mid(String) et de la concaténation

-         Remplacer systématiquement S1.StartsWith(S2) par Instr(S1, S2) = 1  (A moins que vous ne voyez une différence mais...)

-         Idem pour S1.EndsWith(S2)

-         Faire attention aux conversions implicites Integer -> Double (Par contre Double -> Integer ne semble pas poser de problèmes !)

-         Ne pas utiliser les Int16 à moins que le but ne soit de gagner de la mémoire et de perdre du temps

-         Remplacer les Int64 par des Longs

-         Faites vos fonctions Max et Min à la main (Sans fonction mais avec la condition comme dans le tableau)

-         Remplacer les ^ par n facteurs de la base quand c'est possible !!! Ne laissez pas de x ^ 2 dans vos programmes, c'est apparemment 100 fois plus lent que d'écrire x * x

-         Pour les algorithmes utilisant les distances, si vous ne devez que les comparer, inutile de leur appliquer une racine carrée

-         Si possible, utilisez des tableaux à 1 dimension et faites une petite fonction de traduction de 1 paramètre vers x paramètres, par exemple pour un tableau (100,100,100) :

 

    Function Traduction(ByVal x AsInteger, ByVal y AsInteger, ByVal z AsInteger) AsInteger

        Return x * 101 * 101 + y * 101 + z

  End Function

 

Attention toute fois à ce que le code reste lisible, je vous conseille d'effectuer certaines transformations uniquement tout à la fin du projet.

 

N'hésitez pas à faire vos propres tests, le code est tellement simple !

 

Julien.

 

Commentaires

Commentaire de Nurgle le 20/09/2006 22:32:51 administrateur CS

intéressant comme test :-)
certains résultats sont plutôt étonnants...

Commentaire de econs le 23/09/2006 00:13:14 administrateur CS

Les critères de test sont pertinents, et les résultats sont effectivement intéressants.
Pour la comparaison des distances, ne pas faire la racine carrée, c'est bien pensé, mais tu dois pouvoir généraliser celà à toutes les fonctions bijectives croissantes ou décroissantes (comme la racine carrée).
Ex :
Si x > y alors x^3 > y^3 => Pas besoin de calculer le cube. (Pas vrai pour les puissances paires)
Si (x+y)² > (z+t)² alors ln((x+y)²) > ln((z+t)²) ...

Commentaire de olixelle le 29/09/2006 10:11:30

c sympa ton truc :)
ya 2 autres choses qui seraient interresssantes:
- comparaison de for i et for each et while
- comparaison entre appel par valeur et par référence

:)

Commentaire de us_30 le 29/09/2006 21:32:11

Bonsoir,

Une remarque simple qu'on peut faire avec les tests que tu as fait en .NET, avec ceux que j'ai fait en VBA, c'est qu'on arrive aux mêmes conclusions. Le classement par le temps sont identiques. Les grands écarts semblent comparables.

Je retiens, comme Econs, la simple et très pertinente remarque sur la comparaison des expressions, pouvant être effectué sans réaliser nécessairement la totalité du calcul. Attention, toutefois à bien étudier les conditions qui permet de ne pas faire l'intégralité du calcul. Hormis, le cas simple de la distance ou il n'y a pas de risque, d'autres expressions mathématiques peuvent recéler des subtilités. Par exemple, en pensant aux nombres négatifs ou compris entre 0 et 1.

Je retiens également, l'astuce d'une seule dimension pour les tableaux... que je vais de suite tester sous VBA...

En réponse à Olixelle, d'après ce que je sais en VBA :
Pour for i et for each : ce dernier doit être le plus rapide.
Pour While : moins rapide que Do...Loop, lui-même moins rapide que For.
Comparaison entre les appels : par référence est plus rapide que par valeur, mais comme les 2 ne font pas vraiment la même chose, cela n'a pas vraiment un sens de les comparer...

Un p'tit 10/10 !

Amicalement,
Us.

Commentaire de eldim le 13/10/2006 11:23:39

Bonjour,

Merci pour le tuyau c'est important !

Commentaire de abouyassir le 07/11/2006 07:44:27

bonne idée. merci

Commentaire de Adn56 le 22/06/2010 17:41:59

A relire régulierement pendant l'apprentissage de la programmation !
Trés bon tuto, merci. 10/10

 Ajouter un commentaire




Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Février 2012
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
272829    

Consulter la suite du CalendriCode

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,359 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales