C #, For Loops, e teste de velocidade ... Exatamente o mesmo ciclo mais rápido segunda vez?

StackOverflow https://stackoverflow.com/questions/303343

Pergunta

public Int64 ReturnDifferenceA()
{
  User[] arrayList;
  Int64 firstTicks;
  IList<User> userList;
  Int64 secondTicks;
  System.Diagnostics.Stopwatch watch;

  userList = Enumerable
              .Range(0, 1000)
              .Select(currentItem => new User()).ToList();

  arrayList = userList.ToArray();

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

  for (Int32 loopCounter = 0; loopCounter < arrayList.Count(); loopCounter++)
  {
     DoThings(arrayList[loopCounter]);
  }

  watch.Stop();
  firstTicks = watch.ElapsedTicks;

  watch.Reset();
  watch.Start();
  for (Int32 loopCounter = 0; loopCounter < arrayList.Count(); loopCounter++)
  {
     DoThings(arrayList[loopCounter]);
  }
  watch.Stop();
  secondTicks = watch.ElapsedTicks;

  return firstTicks - secondTicks;
}

Como você pode ver, este é realmente simples. Criar uma lista de usuários, força para uma matriz, iniciar um relógio, circuito da lista através de e chamar um método, cronômetro. Repetir. Concluir-se, retornando a diferença da primeira corrida eo segundo.

Agora eu estou chamando com estes:

differenceList = Enumerable
                 .Range(0, 50)
                 .Select(currentItem => ReturnDifferenceA()).ToList();
average = differenceList.Average();

differenceListA = Enumerable
                  .Range(0, 50)
                  .Select(currentItem => ReturnDifferenceA()).ToList();
averageA = differenceListA.Average();

differenceListB = Enumerable
                  .Range(0, 50)
                  .Select(currentItem => ReturnDifferenceA()).ToList();
averageB = differenceListB.Average();

Agora, a parte divertida é que todas as médias são positivas por uma quantidade relativamente grande, variando de 150k a 300k carrapatos.

O que eu não entendo é que eu estou passando a mesma lista, da mesma forma, com o mesmo método e ainda há essa diferença a. Existe algum tipo de cache acontecendo?

Outra coisa interessante é que se eu percorrer a lista antes da primeira seção cronômetro, as médias estão em torno de 5k ou assim.

Foi útil?

Solução

pelo caminho, utilizando IEnumerable.Count () em uma matriz é centenas de vezes mais lento do que Array.length ... Embora isso não responder à pergunta.

Outras dicas

Você está executando em uma linguagem de alto nível com um ambiente de tempo de execução que faz um monte de cache e desempenho otimizações, isso é comum. Às vezes ele é chamado de aquecer a máquina virtual, ou aquecendo o servidor (quando é um aplicativo de produção).

Se algo vai ser feito repetidamente, então você vai com freqüência notar pela primeira vez tem um tempo de execução medido maior e o resto deve estabilizar para uma quantidade menor.

I fazer isso no código MATLAB, e ver que a primeira vez que executar um loop de referência, que leva cinco segundos, e os tempos subsequentes tomar um quinto de segundo. É uma diferença enorme, porque é uma linguagem interpretada que exigia algum tipo de compilação, mas, na realidade, ele não afeta o seu desempenho, porque a grande maioria será 'segunda vez de em qualquer aplicativo de produção.

É bem possível que DoThings () não é para código nativo até a primeira vez que é chamado compilado-JIT.

Porque .NET, como a Plataforma Java, é um ambiente JIT. Todo o código .NET alto nível é compilado para bytecode linguagem intermediária da Microsoft.

Para executar o programa, este bytecode precisa ser compilado / traduzido para código de máquina nativo. No entanto, compilado .NET programado arquivos não são armazenados em código de máquina nativo mas no bytecode máquina virtual intermediária.

A primeira corrida é JIT compilado, por isso levou tempo extra. As execuções subsequentes não precisam mais ser JIT compilado, mas o código nativo é desenhada a partir do cache JIT, portanto, deve ser mais rápido.

Será que você mantenha a sua aplicação se sem terminarem em execuções subseqüentes? Em seguida, a segunda razão é também devido à VM. (VM: 1 = máquina virtual; VM: 2 = memória virtual). Todos os sistemas operacionais generalizadas modernos executar seus processos sobre a memória virtual, que é um mapa de memória real, para permitir que o sistema operacional a capacidade de gerenciar e usar otimizar recursos do sistema. processos menos usados ??são frequentemente arrastados para dentro do cache de disco para permitir que outros processos têm utilização óptima dos recursos.

O processo não estava em memória virtual pela primeira vez, por isso tem de sofrer a sobrecarga de ser arrastado para a memória. Porque, posteriormente, o seu processo estava entre os top-lista mais utilizados recentemente (aka na parte inferior da lista de menos usado recentemente), não foi varrido em cache de disco ainda.

Além disso, os recursos são distribuídos pelo sistema operacional para o processo conforme necessário. Assim, para o primeiro turno, o seu processo tinha que passar por dores de empurrar a contenção envelope com o sistema operacional para expandir seus limites de recursos.

Uma máquina virtual permite .NET e Java para abstrair a maioria dos recursos de programação em uma camada independente máquina, segregando e, portanto, deixando uma bagunça menor para os engenheiros de software dependentes da máquina para lidar com eles. Mesmo que Microsoft Windows é executado em hardware x86 descendente em vez unificada, há diferenças suficientes com diferentes versões do sistema operacional e modelos de CPU para justificar uma máquina virtual abstraída, a fim de dar aos programadores .NET e usuários uma visão consistente.

Você diz que não consegue que fazê-lo 3 vezes, a 2ª e 3ª vezes são relativamente perto. Parece-me que é apenas a primeira vez através do loop que as coisas são lentas.

Eu suspeito que a função que você chama não é Just-In-cronometrado até a primeira corrida. O que você pode tentar é executá-lo uma vez, então pará-lo e executá-lo novamente. Com nenhuma alteração de código, os compila Just-In-Time da execução anterior ainda deve estar ok, e quaisquer otimizações restantes que você vê são o real efeitos cache no trabalho.

Deixe de lado a questão de aquecer o VM ou máquina, de cache, de otimizações JIT, por um momento: o que mais se seu computador está fazendo? Algum dos serviços do sistema 3e42 e thingies bandeja tarefa agarrando alguns CPU? Talvez o seu cliente Steam decidiu verificar se há atualizações, ou IE precisava fazer algo terrivelmente importante, ou o seu programa antivírus ficou no caminho?

Seu teste é tão útil quanto o grau em que você pode isolá-lo de todos os outros programas em execução no seu caixa. Desligue todos os bits de software você pode possivelmente antes de tentar medir a prazo.

Mas então o que eu sei? -. Talvez o seu método de medição é gerido pelo .net (ou qualquer outro) tempo de execução também e contas por apenas tempo de execução 'ciclos virtuais'

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