Calculer le temps d'exécution d'une méthode


Réponses:


1131

Stopwatch est conçu à cet effet et est l'un des meilleurs moyens de mesurer l'exécution du temps dans .NET.

var watch = System.Diagnostics.Stopwatch.StartNew();
// the code that you want to measure comes here
watch.Stop();
var elapsedMs = watch.ElapsedMilliseconds;

N'utilisez pas DateTime pour mesurer l'exécution de l'heure dans .NET.


MISE À JOUR:

Comme indiqué par @ series0ne dans la section des commentaires: Si vous voulez une mesure vraiment précise de l'exécution de certains codes, vous devrez utiliser les compteurs de performances intégrés au système d'exploitation. La réponse suivante contient un bel aperçu.


2
Exactement, et qu'en est-il de ce cas: j'ai une boucle foreach qui a un ThreadPool.QueueUserWorkItem(delegate { CopyFiles(folder, dest); }); intérieur, mais le chronomètre s'arrête avant que tout ne soit fait.
Mahdi Tahsildari

13
@DarinDimitrov - Le chronomètre n'est pas tout à fait exact? rappelez-vous que le bruit de fond .NET (tel que JITing) entraîne des temps d'exécution variables. Par conséquent, de façon réaliste, pour des mesures précises, l'OP devrait utiliser un profileur de performances.
Matthew Layton

3
@ series0ne, très bon point. Je mettrai à jour ma réponse pour inclure votre précieux commentaire.
Darin Dimitrov

7
@DarinDimitrov, j'ai récemment eu un entretien avec un développeur senior très qualifié. Il m'a fait remarquer que l'utilisation de DateTimes est en fait plus précise que l'utilisation d'un chronomètre. Il a dit que la raison en était que le chronomètre dans .NET ne prend pas en compte l'affinité CPU, et donc, si votre thread se déplace d'un cœur à un autre, le chronomètre ne prend pas en compte le temps d'exécution sur les autres cœurs; seul celui où le thread a commencé son exécution. Quelle est ton opinion à ce propos?
Matthew Layton

2
@ series0ne, ce que le développeur principal vous a dit sur le chronomètre et la date et l'heure est absolument vrai. Sauf qu'avec DateTime, vous n'avez pas assez de précision. Le problème est qu'il n'existe aucune classe de ce type dans .NET qui vous permettrait toutes ces fonctionnalités.
Darin Dimitrov

75

Par expérience personnelle, la System.Diagnostics.Stopwatchclasse peut être utilisée pour mesurer le temps d'exécution d'une méthode, cependant ATTENTION : elle n'est pas tout à fait exacte!

Prenons l'exemple suivant:

Stopwatch sw;

for(int index = 0; index < 10; index++)
{
    sw = Stopwatch.StartNew();
    DoSomething();
    Console.WriteLine(sw.ElapsedMilliseconds);
}

sw.Stop();

Exemples de résultats

132ms
4ms
3ms
3ms
2ms
3ms
34ms
2ms
1ms
1ms

Vous vous demandez maintenant; "eh bien pourquoi a-t-il fallu 132 ms la première fois, et nettement moins le reste du temps?"

La réponse est que Stopwatchcela ne compense pas l'activité de «bruit de fond» dans .NET, comme JITing. Par conséquent, la première fois que vous exécutez votre méthode, .NET JIT est la première. Le temps nécessaire pour ce faire s'ajoute au temps de l'exécution. De même, d'autres facteurs feront également varier le temps d'exécution.

Ce que vous devriez vraiment rechercher pour une précision absolue, c'est le profilage des performances !

Jetez un œil à ce qui suit:

RedGate ANTS Performance Profiler est un produit commercial, mais produit des résultats très précis. - Boostez les performances de vos applications avec le profilage .NET

Voici un article StackOverflow sur le profilage: - Quels sont les bons profileurs .NET?

J'ai également écrit un article sur le profilage des performances à l'aide du chronomètre que vous voudrez peut-être consulter - Profilage des performances dans .NET


2
@mahditahsildari Aucun problème. Heureux d'avoir pu aider! :-)
Matthew Layton

41
Je ne sais pas pourquoi c'est un exemple d' inexactitude . Le chronomètre mesure avec précision le coût total du premier appel, ce qui est sûrement ce qui est pertinent pour le client qui va exécuter ce code. Ils ne se soucient pas de savoir si ces 132 millisecondes sont imputées à l'exécution de la méthode ou à la gigue, ils se soucient du temps total écoulé.
Eric Lippert

2
@ series0ne Si vous vous souciez des performances d'une boucle, alors mesurez les performances d'une boucle. Ne supposez pas simplement que faire quelque chose n fois signifie que ce sera exactement n fois plus lent que de l'exécuter une fois.
svick

3
Tout d'abord, l'exemple de code devrait produire la sortie avec un nombre toujours croissant car StopWatch n'est jamais réinitialisé dans la boucle. Et par "devrait" je veux dire que c'est le cas (j'ai vérifié). Votre sortie ne correspond donc pas au code. Deuxièmement, lorsque j'ai corrigé le code pour faire un arrêt / écriture / réinitialisation / démarrage dans la boucle, la première mesure était la même que les autres. Je suppose que votre DoSomething fait quelque chose plus longtemps la première fois qu'il s'exécute. JIT peut être ou non la raison, mais ce n'est pas que le chronomètre affecte la mesure. D'où -1.
ILIA BROUDNO

2
ILIA BROUDNO est absolument correcte, j'ai obtenu les mêmes résultats. @ series0ne, vous avez une Console.WriteLine dans la boucle, écrivant le ms jusqu'à présent; parce que vous n'arrêtez la montre qu'après la fin de la boucle, elle augmente avec le temps à chaque itération, nous devrions donc voir quelque chose comme 3, 6, 10, 12, 15 ... à mesure que le temps s'accumule au fil des exécutions.
Rui Miguel Pinheiro

29

StopWatch la classe recherche votre meilleure solution.

Stopwatch sw = Stopwatch.StartNew();
DoSomeWork();
sw.Stop();

Console.WriteLine("Time taken: {0}ms", sw.Elapsed.TotalMilliseconds);

Il a également un champ statique appelé Stopwatch.IsHighResolution. Bien sûr, il s'agit d'un problème de matériel et de système d'exploitation.

Indique si le minuteur est basé sur un compteur de performances haute résolution.


18

Si vous souhaitez comprendre les performances, la meilleure réponse consiste à utiliser un profileur.

Sinon, System.Diagnostics.StopWatch fournit une minuterie haute résolution.


Absolument correct! Je suis un peu découragé que tant de personnes ici aient suggéré d'utiliser le chronomètre, car il n'est pas tout à fait exact. Cependant, comme vous l'avez suggéré d'utiliser un profileur de performances, c'est la bonne façon de le faire! +1
Matthew Layton

7

StopWatch utilisera le compteur haute résolution

Le chronomètre mesure le temps écoulé en comptant les tics du minuteur dans le mécanisme de minuteur sous-jacent. Si le matériel et le système d'exploitation installés prennent en charge un compteur de performances haute résolution, la classe Chronomètre utilise ce compteur pour mesurer le temps écoulé. Sinon, la classe Chronomètre utilise le minuteur système pour mesurer le temps écoulé. Utilisez les champs Frequency et IsHighResolution pour déterminer la précision et la résolution de l'implémentation du chronométrage.

Si vous mesurez les E / S, vos chiffres seront probablement affectés par des événements externes, et je m'inquiéterais tellement. exactitude (comme vous l'avez indiqué ci-dessus). Au lieu de cela, je prendrais une gamme de mesures et considérerais la moyenne et la distribution de ces chiffres.


0
 using System.Diagnostics;
 class Program
 {
    static void Test1()
    {
        for (int i = 1; i <= 100; i++)
        {
            Console.WriteLine("Test1 " + i);
        }
    }
  static void Main(string[] args)
    {

        Stopwatch sw = new Stopwatch();
        sw.Start();
        Test1();
        sw.Stop();
        Console.WriteLine("Time Taken-->{0}",sw.ElapsedMilliseconds);
   }
 }
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.