Pergunta

Esta questão já tem uma resposta aqui:

Eu estou procurando uma maneira de chamadas de método de referência em C #.

Eu tenho codificado uma estrutura de dados para a atribuição da universidade, e só veio com uma maneira de otimizar um pouco, mas de uma forma que gostaria de acrescentar um pouco de sobrecarga em todas as situações, ao ligar uma chamada O (n) em O (1) em alguns.

Agora eu quero executar ambas as versões contra os dados de teste para ver se vale a pena implementar a otimização. Eu sei que em Ruby, você poderia envolver o código em um bloco de Referência e tê-lo de saída o tempo necessário para executar o bloco na consola - existe algo assim disponível para C #

?
Foi útil?

Solução

Você pode usar o inbuilt classe Cronômetro para "Fornece um conjunto de métodos e propriedades que você pode usar para medir com precisão o tempo decorrido." se você está procurando uma maneira manual para fazê-lo. Não tenho certeza sobre automatizado embora.

Outras dicas

Stolen (e modificada) da resposta 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());
}

Muitas vezes, um método particular tem para inicializar algumas coisas, e nem sempre você quer incluir os custos de inicialização em seu ponto de referência global. Além disso, você quer dividir o tempo total de execução pelo número de iterações, de modo que sua estimativa é mais ou menos independente do número de iterações.

Eu roubei a maioria dos itens a seguir o método de Jon Skeet para aferir:

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);
}

Aqui estão algumas coisas que eu encontrei por tentativa e erro.

  1. Descartar o primeiro lote de (milhares) iterações. Eles provavelmente será afetado pela instabilidade.
  2. Executar o ponto de referência em um objeto Thread separado pode dar resultados melhores e mais estáveis. Eu não sei por quê.
  3. Eu vi algumas pessoas usando Thread.Sleep por qualquer motivo antes de executar o benchmark. Isso só vai piorar as coisas. Eu não sei por quê. Possivelmente devido à instabilidade.
  4. Nunca execute o benchmark com a depuração habilitada. O código provavelmente irá executar ordens de magnitude mais lenta.
  5. compilar o aplicativo com todas as otimizações habilitado. Algum código pode ser drasticamente afetado pela otimização, enquanto outro código não será, de modo a compilar sem otimização afetará a confiabilidade do seu benchmark.
  6. Ao compilar com otimizações habilitado, às vezes é necessário algum modo avaliar a saída do índice de referência (por exemplo, imprimir um valor, etc). Caso contrário, o compilador pode 'descobrir' alguns cálculos são inúteis e não simplesmente realizá-las.
  7. Invocation de delegados pode ter sobrecarga perceptível quando executar determinados benchmarks. É melhor colocar mais de uma iteração dentro do delegado, de modo que a sobrecarga tem pouco efeito sobre o resultado do benchmark.
  8. Profilers pode ter seu próprio teto. Eles são bons em dizer-lhe que partes do código são gargalos, mas não é bom, na verdade, o benchmarking duas coisas diferentes de forma confiável.
  9. Em geral, as soluções de benchmarking fantasia pode ter sobrecarga perceptível. Por exemplo, se você quiser de referência muitos objetos usando uma única interface, pode ser tentador para embrulhar cada objeto em uma classe. No entanto, lembre-se que o construtor da classe também tem sobrecarga que deve ser levado em conta. É melhor manter tudo o mais simples e direta possível.

Parece que você quer um profiler . Eu recomendaria fortemente a EQATEC profiler mim mesmo, sendo o melhor livre que eu tentei. A coisa agradável sobre este método ao longo de um simples cronômetro é que ele também fornece uma análise do desempenho ao longo certos métodos / blocos.

Profilers dar os melhores benchmarks desde que diagnosticar todo o seu código, no entanto, eles retardá-lo muito. Profilers são usados ??para encontrar gargalos.

Para otimizar um algoritmo, quando você sabe quais são os gargalos, use um dicionário de nome -> cronômetro, para acompanhar as seções críticas de desempenho durante o tempo de execução

.
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top