Preciso encontrar um gargalo e medir o tempo com a maior precisão possível.
O trecho de código a seguir é a melhor maneira de medir o desempenho?
DateTime startTime = DateTime.Now;
// Some execution process
DateTime endTime = DateTime.Now;
TimeSpan totalTimeTaken = endTime.Subtract(startTime);
Respostas:
Não, não é. Use o cronômetro (pol
System.Diagnostics
)O cronômetro verifica automaticamente a existência de temporizadores de alta precisão.
Vale ressaltar que
DateTime.Now
muitas vezes é um pouco mais lento do queDateTime.UtcNow
devido ao trabalho que deve ser feito com fusos horários, horário de verão e tal.DateTime.UtcNow normalmente tem uma resolução de 15 ms. Ver a publicação de blog de John Chapman sobre
DateTime.Now
precisão para obter um ótimo resumo.Curiosidades interessantes: o cronômetro volta a funcionar
DateTime.UtcNow
se o seu hardware não suportar um contador de alta frequência. Você pode verificar se o Stopwatch usa hardware para obter alta precisão observando o campo estático Stopwatch.IsHighResolution .fonte
PerformWork()
for muito curto, poderá chamá-lo repetidamente e calcular a média do lote de chamadas. Além disso, programe um lote inteiro de chamadas, em vez de iniciar / interromper o seu,Stopwatch
para evitar um efeito estroboscópico que prejudicará suas medições de tempo.Se você quiser algo rápido e sujo, sugiro usar o cronômetro para obter um maior grau de precisão.
Como alternativa, se você precisar de algo um pouco mais sofisticado, provavelmente considere usar um criador de perfil de terceiros, como o ANTS .
fonte
Este artigo diz que antes de tudo é preciso comparar três alternativas,
Stopwatch
,DateTime.Now
EDateTime.UtcNow
.Também mostra que, em alguns casos (quando o contador de desempenho não existe), o cronômetro está usando o DateTime.UtcNow + algum processamento extra. Por isso, é óbvio que, nesse caso, DateTime.UtcNow é a melhor opção (porque outros a usam + algum processamento)
No entanto, como se vê, o contador quase sempre existe - consulte Explicação sobre o contador de desempenho de alta resolução e sua existência relacionada ao .NET Stopwatch. .
Aqui está um gráfico de desempenho. Observe como o UtcNow de baixo desempenho compara-se às alternativas:
O eixo X é o tamanho dos dados da amostra e o eixo Y é o tempo relativo do exemplo.
Uma coisa
Stopwatch
é melhor: ele fornece medições de tempo de resolução mais alta. Outra é a sua natureza mais OO. No entanto, criar um wrapper OOUtcNow
não pode ser difícil.fonte
É útil inserir seu código de benchmarking em uma classe / método de utilitário. A
StopWatch
classe não precisa estarDisposed
ou estarStopped
errada. Portanto, o código mais simples para cronometrar alguma ação éCódigo de chamada de amostra
Aqui está a versão do método de extensão
E código de chamada de amostra
fonte
Elapsed.TotalMilliseconds
para maior precisão. Veja também esta questão stackoverflow.com/questions/8894425/…A funcionalidade do cronômetro seria melhor (maior precisão). Eu também recomendaria apenas baixar um dos criadores de perfil populares ( DotTrace e ANTS são os que eu mais usei ... a avaliação gratuita do DotTrace é totalmente funcional e não incomoda como alguns dos outros).
fonte
Use a classe System.Diagnostics.Stopwatch.
fonte
O mesmo cronômetro, é muito melhor.
Em relação à medição de desempenho, você também deve verificar se o seu "// Some Execution Process" é um processo muito curto.
Lembre-se também de que a primeira execução do seu "// Some Execution Process" pode ser muito mais lenta que as execuções subsequentes.
Normalmente, testo um método executando-o 1000 vezes ou 1000000 vezes em um loop e obtenho dados muito mais precisos do que executá-lo uma vez.
fonte
Todas essas são ótimas maneiras de medir o tempo, mas essa é apenas uma maneira muito indireta de encontrar gargalos.
A maneira mais direta de encontrar um gargalo em um encadeamento é fazê-lo funcionar e, enquanto faz o que quer que você espere, pare-o com uma tecla de pausa ou quebra. Faça isso várias vezes. Se o seu gargalo demorar X% do tempo, X% é a probabilidade de você capturá-lo em flagrante em cada instantâneo.
Aqui está uma explicação mais completa de como e por que funciona
fonte
@ Sean Chambers
FYI, a classe .NET Timer não é para diagnóstico, ela gera eventos em um intervalo predefinido, como este (do MSDN ):
Portanto, isso realmente não ajuda a saber quanto tempo levou algo, apenas que uma certa quantidade de tempo se passou.
O cronômetro também é exposto como um controle no System.Windows.Forms ... você pode encontrá-lo na caixa de ferramentas do designer no VS05 / VS08
fonte
Esta é a maneira correta:
Para obter mais informações, consulte Usar o cronômetro em vez do DataTime para obter um contador de desempenho preciso .
fonte
O Visual Studio Team System possui alguns recursos que podem ajudar com esse problema. Essencialmente, você pode escrever testes de unidade e misturá-los em diferentes cenários para executar no seu software como parte de um teste de estresse ou carga. Isso pode ajudar a identificar áreas de código que mais afetam o desempenho de seus aplicativos.
O grupo de Padrões e práticas da Microsoft tem algumas orientações nas Diretrizes de teste de desempenho do sistema de equipes do Visual Studio .
fonte
Acabei de encontrar um post no blog de Vance Morrison sobre uma classe CodeTimer que ele escreveu que facilita o uso
StopWatch
e faz algumas coisas legais ao lado.fonte
Isso não é profissional o suficiente:
Uma versão mais confiável é:
No meu código real, adicionarei a chamada GC.Collect para alterar o heap gerenciado para um estado conhecido e adicionarei a chamada Sleep, para que diferentes intervalos de código possam ser facilmente separados no perfil ETW.
fonte
Eu fiz muito pouco desse tipo de verificação de desempenho (eu costumo pensar "isso é lento, torna-o mais rápido"), então eu sempre o segui.
Um google revela muitos recursos / artigos para verificação de desempenho.
Muitos mencionam o uso do pinvoke para obter informações de desempenho. Muitos dos materiais que estudo apenas mencionam o uso de perfmon.
Editar:
Vi as palestras do StopWatch. Eu aprendi algo :)
Parece um bom artigo
fonte
A maneira como uso em meus programas é usando a classe StopWatch, como mostrado aqui.
fonte