104 votes

Analyse comparative des échantillons de la taille du code en c#, cette implémentation est perfectible ?

Assez souvent, DONC je me retrouve à l'analyse comparative des petits morceaux de code pour voir ce qui implemnetation est la plus rapide.

Assez souvent je vois des commentaires que l'analyse comparative code ne prend pas en compte jitting ou le garbage collector.

J'ai le simple suivant l'analyse comparative de la fonction qui j'ai évolué tout doucement:

  static void Profile(string description, int iterations, Action func) {
        // warm up 
        func();
        // clean up
        GC.Collect();

        var watch = new Stopwatch();
        watch.Start();
        for (int i = 0; i < iterations; i++) {
            func();
        }
        watch.Stop();
        Console.Write(description);
        Console.WriteLine(" Time Elapsed {0} ms", watch.ElapsedMilliseconds);
    }

Utilisation:

Profile("a descriptions", how_many_iterations_to_run, () =>
{
   // ... code being profiled
});

Cette mise en œuvre n'a pas de défauts? Est-il assez bon pour montrer que implementaion X est plus rapide que la mise en œuvre de Y sur Z itérations? Pouvez-vous penser à des façons de vous améliorer?

MODIFIER Son assez clair que le temps, en fonction de l'approche (par opposition à d'itérations), de préférence, quelqu'un a une implémentations où les contrôles ne sont pas d'incidence sur les performances?

93voto

Sam Saffron Points 56236

Voici la fonction modifiée : tel que recommandé par la Communauté, n’hésitez pas à modifier ce qu’il est un wiki de la communauté.

22voto

LukeH Points 110965

Finalisation de ne pas nécessairement être complété avant d' GC.Collect de rendement. La finalisation est en file d'attente et ensuite l'exécuter sur un thread séparé. Ce fil pourrait encore être actif lors de vos tests, influant sur les résultats.

Si vous voulez vous assurer que la finalisation a terminé avant de commencer vos tests, alors vous voudrez peut-être appeler GC.WaitForPendingFinalizers, ce qui permet de bloquer jusqu'à la finalisation de la file d'attente est désactivée:

GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();

15voto

Jonathan Rupp Points 10900

Si vous voulez prendre GC interactions de l'équation, vous pouvez exécuter votre "chauffer" appel après la GC.Appel à frais virés, pas avant. De cette façon, vous savez .NET aura déjà assez de mémoire allouée à partir du système d'exploitation pour l'ensemble de travail de votre fonction.

Gardez à l'esprit que vous êtes non-inline à l'appel de la méthode pour chaque itération, alors assurez-vous de comparer les choses que vous faites des tests pour le corps est vide. Vous devrez également accepter que vous ne pouvez de manière fiable le temps les choses qui sont plusieurs fois plus longtemps qu'un appel de méthode.

Aussi, en fonction de ce genre de choses que l'on profilage, vous pouvez faire votre emploi du temps en fonction en cours d'exécution pour un certain laps de temps plutôt que pour un certain nombre d'itérations, il peut ont tendance à conduire plus facilement comparables numéros sans avoir à disposer d'un très court terme pour la meilleure mise en œuvre et/ou d'un très long pour le pire.

6voto

Alex Yakunin Points 3523

J'aimerais éviter de passer le délégué du tout:

  1. Déléguer l'appel est ~ virtuel appel de méthode. Pas cher: ~ 25% de la plus petite allocation de mémoire .NET. Si vous êtes intéressé par les détails, voir par exemple ce lien.
  2. Anonyme les délégués peuvent conduire à l'utilisation de fermetures, que vous ne remarquerez même pas. De nouveau, l'accès à la fermeture des champs est sensiblement que, par exemple, de l'accès à une variable sur la pile.

Un exemple de code conduisant à la fermeture d'utilisation:

public void Test()
{
  int someNumber = 1;
  Profiler.Profile("Closure access", 1000000, 
    () => someNumber + someNumber);
}

Si vous n'êtes pas au courant au sujet de fermetures, jetez un oeil à cette méthode .NET Réflecteur.

6voto

Paul Alexander Points 17611

Je pense que le problème le plus difficile à surmonter avec l'analyse comparative des méthodes comme c'est la cas de bord et de l'inattendu. Par exemple: "Comment les deux extraits de code de travail sous forte charge CPU/utilisation du réseau/surcharge du disque/etc". Ils sont grands pour la logique de base des vérifications pour voir si un algorithme fonctionne sensiblement plus vite que l'autre. Mais pour bien tester les performances du code, vous devez créer un test qui mesure les goulots d'étranglement spécifiques du code.

Je voudrais encore dire que les tests de dépistage de petits blocs de code a souvent que peu de retour sur investissement et encourager l'aide d'un code trop complexe au lieu d'une simple code maintenable. L'écriture d'un code clair que d'autres développeurs, ou moi-même 6 mois sur toute la ligne, peuvent comprendre rapidement aura plus d'avantages de performance de haut de code optimisé.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X