web-dev-qa-db-fra.com

Mesurer le temps d'exécution en C #

Je veux mesurer l'exécution d'un morceau de code et je me demande quelle est la meilleure méthode pour faire cela est?

Option 1:

DateTime StartTime = DateTime.Now;

//Code

TimeSpan ts = DateTime.Now.Subtract(StartTime);
string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
        ts.Hours, ts.Minutes, ts.Seconds,
        ts.Milliseconds / 10);
Console.WriteLine(elapsedTime, "RunTime");

Option 2: Utiliser System.Diagnostics;

    Stopwatch stopWatch = new Stopwatch();
    stopWatch.Start();

    //Code

    stopWatch.Stop();
    // Get the elapsed time as a TimeSpan value.
    TimeSpan ts = stopWatch.Elapsed;

    // Format and display the TimeSpan value.
    string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
        ts.Hours, ts.Minutes, ts.Seconds,
        ts.Milliseconds / 10);
    Console.WriteLine(elapsedTime, "RunTime");

Ce n'est pas simplement pour l'analyse comparative, sa partie réellement de l'application. Le moment où la fonction prend pour exécuter est des données pertinentes. Il n'a toutefois pas besoin d'être atomique ou hyper-précon.

Quelle option est meilleure pour le code de production ou quelqu'un d'autre utilise-t-il quelque chose de différent et peut-être mieux?

37
Jake

La classe Stopwatch est spécialement conçue pour mesurer le temps écoulé et peut (si disponible sur votre matériel) offre une bonne granularité/précision à l'aide d'une minuterie matérielle à haute fréquence sous-jacente. Donc cela semble le meilleur choix.

Le iShighresolution Property peut être utilisé pour déterminer si le calendrier de haute résolution est disponible. Pour la documentation, cette classe offre une enveloppe sur les API Win32 "meilleures disponibles" pour une minuterie précise:

Spécifiquement, le champ FrequencyGetTimestamp méthode peut être utilisé à la place des API Win32 non gérés QueryPerformanceFrequency et QueryPerformanceCounter.

Il y a des antécédents détaillés sur ces API Win32 [ici] et dans les documents MSDN liés 2 .

Minuterie haute résolution

Un compteur est un terme général utilisé dans la programmation pour faire référence à une variable d'incrémentation. Certains systèmes comprennent un compteur de performance haute résolution qui fournit des temps écoulés à haute résolution.

Si un compteur de performance haute résolution existe sur le système, vous pouvez utiliser la fonction QueryPerformanceFréquence Fonction pour exprimer la fréquence, dans le nombre de comptes par seconde. La valeur du nombre est du processeur dépendante. Sur certains processeurs, par exemple, le nombre peut être le taux de cycle de l'horloge de processeur.

Le QueryPerformEcanceCounter La fonction récupère la valeur actuelle du compteur de performances haute résolution. En appelant cette fonction au début et à la fin d'une section du code, une application utilise essentiellement le comptoir en tant que minuterie haute résolution. Par exemple, supposons que QueryPerformanceFréquence indique que la fréquence du compteur de performances haute résolution est de 50 000 comptes par seconde. Si l'application appelle QueryPerformancecounter immédiatement avant et immédiatement après la section de code à expiration, les valeurs de compteur peuvent être respectivement de 1500 comptes et 3500 chefs de comptabilisation. Ces valeurs indiquaient que .04 secondes (2000 comptes) écoulées pendant que le code est exécuté.

28
Steve Townsend

Ce n'est pas seulement que StopWatch est plus précis, mais aussi que DateTime.Now donnera des résultats incorrects dans certaines circonstances.

Considérez ce qui se passe pendant une heure d'économie de jour, par exemple - en utilisant DateTime.Now peut réellement donner une réponse négatif!

13
porges

J'utilise généralement StopWatch pour ce genre de situation.

De MSDN page:

chronomètre

Fournit un ensemble de méthodes et de propriétés que vous pouvez utiliser pour mesurer avec précision le temps écoulé.

Dans le message suivant, je l'utilise pour comparer l'heure d'exécution de Linq vs plinq:

LINQ parallèle (plinq) avec Visual Studio 201

6
Leniel Maccaferri

Ni vous fera mal à la performance, parce que vous dites que ce n'est pas si critique. Le chronomètre semble plus approprié - vous ne souscrivez que le temps de soustraire de temps et non d'une date d'une autre. Date Stuff prend un TAD plus de mémoire et de la CPU temps pour traiter. Il existe également des moyens de créer le Code Nettoyant, au cas où vous prévoyez de la réutiliser à plusieurs endroits. Surcharge using vous vient à l'esprit. Je vais chercher un exemple. OK, code volé de:

http://stevesmithblog.com/blog/great-Une-of-utilisation-statement-in-c/

public class ConsoleAutoStopWatch : IDisposable
{
    private readonly Stopwatch _stopWatch;

    public ConsoleAutoStopWatch()
    {
        _stopWatch = new Stopwatch();
        _stopWatch.Start();
    }

    public void Dispose()
    {
        _stopWatch.Stop();
        TimeSpan ts = _stopWatch.Elapsed;

        string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
                                           ts.Hours, ts.Minutes, ts.Seconds,
                                           ts.Milliseconds / 10);
        Console.WriteLine(elapsedTime, "RunTime");
    }
}

private static void UsingStopWatchUsage()
{
    Console.WriteLine("ConsoleAutoStopWatch Used: ");
    using (new ConsoleAutoStopWatch())
    {
        Thread.Sleep(3000);
    }
}
5
Hamish Grubijan

Les deux vont probablement correspondre à vos besoins très bien, mais je dirais utiliser StopWatch. Pourquoi? Parce que c'est destiné à la tâche que vous faites.

Vous avez une classe qui est construite pour renvoyer la date/heure actuelle, qui, comme cela se produit peut être utilisée pour des choses chronométrées et que vous avez une classe spécialement conçue pour les choses chronométrées.

Dans ce cas, les différences n'existent vraiment que si vous avez besoin de précision de milliseconde (auquel cas StopWatch est plus précis), mais en tant que directeur général si un outil existe spécifiquement pour la tâche que vous recherchez alors c'est le meilleur un à utiliser.

1
fyjham

J'ai une petite classe pour faire ce genre de chose ad hoc. Il utilise la classe de chronomètre - C # Micro Perfomance Test .

par exemple.

var tester = new PerformanceTester(() => SomeMethod());
tester.MeasureExecTime(1000);
Console.Writeline(string.Format("Executed in {0} milliseconds", tester.AverageTime.TotalMilliseconds));
1
Luke Lowrey

Utilisez ci-dessous le code

DateTime dExecutionTime;
dExecutionTime = DateTime.Now;
      TimeSpan span = DateTime.Now.Subtract(dExecutionTime);
                  lblExecutinTime.Text = "total time taken " +   Math.Round(span.TotalMinutes,2) + " minutes .   >>---> " + DateTime.Now.ToShortTimeString();
0
parvez

J'ai pris la réponse de Hamish la simplifiait et a rendu un peu plus général au cas où vous auriez besoin de vous connecter ailleurs:

public class AutoStopWatch : Stopwatch, IDisposable {

    public AutoStopWatch() {
        Start();
    }

    public virtual void Dispose() {
        Stop();
    }
}

 public class AutoStopWatchConsole : AutoStopWatch {

    private readonly string prefix;

    public AutoStopWatchConsole(string prefix = "") {
        this.prefix = prefix;
    }

    public override void Dispose() {
        base.Dispose();

        string format = Elapsed.Days > 0 ? "{0} days " : "";
        format += "{1:00}:{2:00}:{3:00}.{4:00}";

        Console.WriteLine(prefix + " " + format.Format(Elapsed.Days, Elapsed.Hours, Elapsed.Minutes, Elapsed.Seconds, Elapsed.Milliseconds / 10));
    }
}

private static void Usage() {

    Console.WriteLine("AutoStopWatch Used: ");
    using (var sw = new AutoStopWatch()) {
        Thread.Sleep(3000);

        Console.WriteLine(sw.Elapsed.ToString("h'h 'm'm 's's'"));
    }

    Console.WriteLine("AutoStopWatchConsole Used: ");
    using (var sw = new AutoStopWatchConsole()) {
        Thread.Sleep(3000);
    }

}
0
katbyte