Calcular o tempo de execução de um método

Respostas:

1131

Stopwatch foi desenvolvido para esse fim e é uma das melhores maneiras de medir a execução do tempo no .NET.

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

Não use DateTime para medir a execução do tempo no .NET.


ATUALIZAR:

Conforme apontado por @ series0ne na seção de comentários: Se você deseja uma medição realmente precisa da execução de algum código, precisará usar os contadores de desempenho incorporados ao sistema operacional. A resposta a seguir contém uma boa visão geral.

Darin Dimitrov
fonte
2
Exatamente, e o que dizer deste caso: eu tenho um loop foreach que tem um ThreadPool.QueueUserWorkItem(delegate { CopyFiles(folder, dest); }); interior, mas o cronômetro para antes que tudo seja feito.
Mahdi Tahsildari
13
@DarinDimitrov - O cronômetro não é totalmente preciso? lembre-se de que o ruído de fundo do .NET (como JITing) causa tempos de execução variados. Portanto, realisticamente, para medições precisas, o OP deve estar usando um perfil de desempenho.
Matthew Layton
3
@ series0ne, ponto muito bom. Vou atualizar minha resposta para incluir seu comentário valioso.
precisa
7
@DarinDimitrov, recentemente tive uma entrevista com um desenvolvedor sênior muito qualificado. Ele apontou para mim que o uso do DateTimes é realmente mais preciso do que o uso de um StopWatch. Ele disse que a razão para isso é que o cronômetro no .NET não leva em consideração a afinidade da CPU e, portanto, se o encadeamento se move de um núcleo para outro, o StopWatch não leva em consideração o tempo de execução nos outros núcleos; somente aquele em que o encadeamento começou a execução. Qual a sua opinião sobre isso?
Matthew Layton
2
@ series0ne, o que o desenvolvedor sênior disse sobre o cronômetro e o DateTime é absolutamente verdadeiro. Exceto que, com o DateTime, você não tem precisão suficiente. O problema é que não existe essa classe no .NET que permita todos esses recursos.
Darin Dimitrov
75

Por experiência pessoal, a System.Diagnostics.Stopwatchclasse pode ser usada para medir o tempo de execução de um método, no entanto, CUIDADO : Não é totalmente preciso!

Considere o seguinte exemplo:

Stopwatch sw;

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

sw.Stop();

Resultados de exemplo

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

Agora você está se perguntando; "bem, por que demorou 132ms na primeira vez e significativamente menos no restante do tempo?"

A resposta é que Stopwatchnão compensa a atividade de "ruído de fundo" no .NET, como o JITing. Portanto, na primeira vez em que você executa seu método, o .NET JIT é o primeiro. O tempo que leva para fazer isso é adicionado ao tempo da execução. Da mesma forma, outros fatores também farão com que o tempo de execução varie.

O que você realmente deveria procurar por precisão absoluta é o Perfil de Desempenho !

Dê uma olhada no seguinte:

O RedGate ANTS Performance Profiler é um produto comercial, mas produz resultados muito precisos. - Melhore o desempenho de seus aplicativos com o perfil .NET

Aqui está um artigo do StackOverflow sobre criação de perfil: - Quais são alguns bons perfis de .NET .NET?

Também escrevi um artigo sobre o perfil de desempenho usando cronômetro que você pode querer olhar - perfil de desempenho no .NET

Matthew Layton
fonte
2
@mahditahsildari Sem problemas. Ainda bem que pude ajudar! :-)
Matthew Layton
41
Não sei por que esse é um exemplo de imprecisão . O cronômetro está medindo com precisão o custo total da primeira chamada, que certamente é o que é relevante para o cliente que executará esse código. Eles não se importam se esses 132 milissegundos são cobrados na execução do método ou na instabilidade, eles se importam com o tempo total decorrido.
precisa
2
@ series0ne Se você se preocupa com o desempenho de um loop, meça o desempenho de um loop. Não basta assumir que fazer algo n vezes significa que será exatamente n vezes mais lento que executá-lo uma vez.
svick
3
Primeiro, o exemplo de código deve produzir a saída com um número cada vez maior, pois o StopWatch nunca é redefinido no loop. E com "deveria", quero dizer que sim (verifiquei). Portanto, sua saída não corresponde ao código. Segundo, quando eu corrigi o código para fazer um Stop / Write / Reset / Start no loop, a primeira medição foi a mesma que as demais. Meu palpite é que o seu DoSomething faz algo por mais tempo na primeira vez em que é executado. O JIT pode ou não ser o motivo disso, mas não é que o cronômetro esteja afetando a medição. Portanto -1.
ILIA BROUDNO
2
ILIA BROUDNO está absolutamente correta, obtive os mesmos resultados. @ series0ne, você tem um Console.WriteLine dentro do loop, escrevendo os ms até agora; porque você só para o relógio APÓS o loop terminar, está aumentando ao longo do tempo a cada iteração, portanto, devemos ver algo como 3, 6, 10, 12, 15 ... à medida que o tempo se acumula nas execuções.
Rui Miguel Pinheiro
29

StopWatch A classe procura sua melhor solução.

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

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

Também possui um campo estático chamado Stopwatch.IsHighResolution. Obviamente, esse é um problema de hardware e sistema operacional.

Indica se o cronômetro é baseado em um contador de desempenho de alta resolução.

Soner Gönül
fonte
18

Se você estiver interessado em entender o desempenho, a melhor resposta é usar um criador de perfil.

Caso contrário, System.Diagnostics.StopWatch fornece um timer de alta resolução.

Jeff Foster
fonte
Absolutamente correto! Estou um pouco desanimado por tantas pessoas sugerirem o uso do cronômetro, pois ele não é totalmente preciso. No entanto, como você sugeriu usar um criador de perfil de desempenho, esta é a maneira correta de fazer isso! 1
Matthew Layton
7

O StopWatch usará o contador de alta resolução

O cronômetro mede o tempo decorrido contando os tiques do cronômetro no mecanismo subjacente do cronômetro. Se o hardware e o sistema operacional instalados suportarem um contador de desempenho de alta resolução, a classe Stopwatch utilizará esse contador para medir o tempo decorrido. Caso contrário, a classe Stopwatch usa o timer do sistema para medir o tempo decorrido. Use os campos Frequency e IsHighResolution para determinar a precisão e a resolução da implementação do tempo do cronômetro.

Se você estiver medindo IO, seus números provavelmente serão impactados por eventos externos, e eu me preocuparia muito. exatidão (como você indicou acima). Em vez disso, eu faria uma série de medições e consideraria a média e a distribuição desses números.

Brian Agnew
fonte
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);
   }
 }
Md.Rakibuz Sultan
fonte