Question

    

Cette question a déjà une réponse ici:

         

Je cherche un moyen de comparer les appels de méthode en C #.

J'ai codé une structure de données pour une affectation universitaire et je viens juste de trouver un moyen d'optimiser un bit, mais d'une manière qui ajouterait un peu de surcharge dans toutes les situations, tout en transformant un appel O (n) en O (1) dans certains.

Maintenant, je veux exécuter les deux versions sur les données de test pour voir si cela vaut la peine d'implémenter l'optimisation. Je sais qu’en Ruby, vous pouvez envelopper le code dans un bloc de référence et l’indiquer le temps nécessaire à l’exécution du bloc dans la console. Existe-t-il quelque chose de similaire pour C #?

Était-ce utile?

La solution

Vous pouvez utiliser la classe Chronomètre incorporée pour "Fournit un ensemble de méthodes et de propriétés que vous pouvez utiliser pour mesurer avec précision le temps écoulé." si vous cherchez un moyen manuel de le faire. Pas sûr si automatisé.

Autres conseils

Volé (et modifié) de la réponse de Yuriy:

private static void Benchmark(Action act, int iterations)
{
    GC.Collect();
    act.Invoke(); // run once outside of loop to avoid initialization costs
    Stopwatch sw = Stopwatch.StartNew();
    for (int i = 0; i < iterations; i++)
    {
        act.Invoke();
    }
    sw.Stop();
    Console.WriteLine((sw.ElapsedMilliseconds / iterations).ToString());
}

Souvent, une méthode particulière doit initialiser certaines choses et vous ne souhaitez pas toujours inclure ces coûts d'initialisation dans votre référence globale. En outre, vous souhaitez diviser le temps total d’exécution par le nombre d’itérations, de sorte que votre estimation soit plus ou moins indépendante du nombre d’itérations.

J'ai volé la plupart des éléments suivants de la méthode d'analyse comparative de Jon Skeet:

private static void Benchmark(Action act, int interval)
{
    GC.Collect();
    Stopwatch sw = Stopwatch.StartNew();
    for (int i = 0; i < interval; i++)
    {
        act.Invoke();
    }
    sw.Stop();
    Console.WriteLine(sw.ElapsedMilliseconds);
}

Voici certaines choses que j'ai trouvées par essais et erreurs.

  1. Supprimez le premier lot d'itérations (en milliers). Ils seront probablement touchés par le Jitter.
  2. L'exécution du test de référence sur un objet Thread distinct peut donner des résultats meilleurs et plus stables. Je ne sais pas pourquoi.
  3. J'ai déjà vu des personnes utiliser Thread.Sleep pour une raison quelconque avant d'exécuter le point de repère. Cela ne fera qu'empirer les choses. Je ne sais pas pourquoi. Peut-être à cause de la JITter.
  4. N'exécutez jamais le test de performance avec le débogage activé. Le code sera probablement exécuter des ordres de grandeur plus lent.
  5. Compilez votre application avec toutes les optimisations activées. L’optimisation peut affecter considérablement certains codes, alors que d’autres ne le seront pas. Par conséquent, la compilation sans optimisation affectera la fiabilité de votre référence.
  6. Lors de la compilation avec les optimisations activées, il est parfois nécessaire d’évaluer en quelque sorte la sortie du test (par exemple, imprimer une valeur, etc.). Sinon, le compilateur peut "comprendre" certains calculs sont inutiles et ne les exécutera tout simplement pas.
  7. L'invocation de délégués peut entraîner une surcharge considérable lors de l'exécution de certains tests de performance. Il est préférable d’insérer plus d’une itération dans le délégué, afin que les frais généraux aient peu d’effet sur le résultat du test.
  8. Les profileurs peuvent avoir leurs propres frais généraux. Ils savent bien quelles parties de votre code constituent des goulots d'étranglement, mais pas vraiment pour évaluer de manière fiable deux choses différentes.
  9. En règle générale, les solutions d'analyse comparative sophistiquées peuvent entraîner des frais généraux considérables. Par exemple, si vous souhaitez analyser plusieurs objets à l'aide d'une seule interface, il peut être tentant d'envelopper chaque objet dans une classe. Cependant, rappelez-vous que le constructeur de classe a également une surcharge qui doit être prise en compte. Il est préférable de tout garder aussi simple et direct que possible.

On dirait que vous voulez un profileur . Je recommanderais vivement le profileur EQATEC , le meilleur que j'ai jamais essayé. La bonne chose à propos de cette méthode par rapport à un simple chronomètre est qu’elle fournit également une ventilation des performances sur certaines méthodes / blocs.

Les profileurs donnent les meilleurs tests car ils diagnostiquent tout votre code, mais ils le ralentissent beaucoup. Les profileurs sont utilisés pour rechercher les goulots d'étranglement.

Pour optimiser un algorithme lorsque vous savez où se trouvent les goulots d'étranglement, utilisez un dictionnaire contenant le nom - > chronomètre pour suivre les sections critiques en termes de performances lors de l'exécution.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top