Existem funções de temporização em JavaScript com resolução de microssegundos?
Estou ciente de timer.js para Chrome e espero que haja uma solução para outros navegadores amigáveis, como Firefox, Safari, Opera, Epiphany, Konqueror, etc. Não estou interessado em oferecer suporte a nenhum IE, mas respostas incluindo o IE são bem-vindos.
(Dada a baixa precisão do tempo de milissegundos em JS, não estou prendendo a respiração neste aqui!)
Atualização: timer.js anuncia resolução de microssegundos, mas simplesmente multiplica a leitura de milissegundos por 1.000. Verificado por teste e inspeção de código. Decepcionado. : [
javascript
mwcz
fonte
fonte
Respostas:
Como aludido na resposta de Mark Rejhon, há uma API disponível em navegadores modernos que expõe dados de tempo de resolução de submilissegundos para o script: o W3C High Resolution Timer , também conhecido como
window.performance.now()
.now()
é melhor do que o tradicionalDate.getTime()
de duas maneiras importantes:now()
é um duplo com resolução de submilissegundos que representa o número de milissegundos desde o início da navegação da página. Ele retorna o número de microssegundos na fracionária (por exemplo, um valor de 1000,123 é 1 segundo e 123 microssegundos).now()
está aumentando monotonicamente. Isto é importante porqueDate.getTime()
pode possivelmente saltar para a frente ou mesmo para trás em chamadas subseqüentes. Notavelmente, se a hora do sistema do SO for atualizada (por exemplo, sincronização do relógio atômico),Date.getTime()
também será atualizado.now()
tem a garantia de estar sempre aumentando monotonicamente, portanto, não é afetado pela hora do sistema do SO - será sempre a hora do relógio de parede (assumindo que seu relógio de parede não seja atômico ...).now()
pode ser usado em quase todos os lugares quenew Date.getTime()
,+ new Date
eDate.now()
são. A exceção é queDate
e osnow()
tempos não se misturam, poisDate
é baseado em unix-epoch (o número de milissegundos desde 1970), enquantonow()
é o número de milissegundos desde que sua navegação na página começou (portanto, será muito menor queDate
).now()
é compatível com o Chrome estável, Firefox 15+ e IE10. Existem também vários polyfills disponíveis.fonte
new Date.getTime()
não é uma coisa.new Date().getTime()
é.console.log
em cada execução) Difícil de decifrar, mas copie todo o código destacado aqui:last=-11; same=0; runs=100; for(let i=0;i<runs;i++) { let now = performance.now(); console.log('.'); if (now === last) { same++; } last = now; } console.log(same, 'were the same');
Agora existe um novo método de medição de microssegundos em javascript: http://gent.ilcore.com/2012/06/better-timer-for-javascript.html
No entanto, no passado, descobri um método bruto de obter precisão de 0,1 milissegundo em JavaScript a partir de um cronômetro de milissegundo. Impossível? Não. Continue lendo:
Estou fazendo alguns experimentos de alta precisão que exigem precisões de cronômetro verificadas automaticamente, e descobri que consegui obter uma precisão de 0,1 milissegundo de maneira confiável com certos navegadores em certos sistemas.
Descobri que, em navegadores modernos com aceleração por GPU em sistemas rápidos (por exemplo, i7 quad core, onde vários núcleos estão ociosos, apenas a janela do navegador) - agora posso confiar que os temporizadores têm precisão de milissegundos. Na verdade, ele se tornou tão preciso em um sistema i7 ocioso que consegui obter com segurança exatamente o mesmo milissegundo, em mais de 1.000 tentativas. Somente quando estou tentando fazer coisas como carregar uma página da web extra, ou outro, a precisão de milissegundos degrada (E eu sou capaz de capturar minha própria precisão degradada fazendo uma verificação de tempo antes e depois, para ver se meu tempo de processamento aumentou repentinamente para 1 ou mais milissegundos - isso me ajuda a invalidar resultados que provavelmente foram afetados de maneira adversa pelas flutuações da CPU).
Tornou-se tão preciso em alguns navegadores acelerados por GPU em sistemas i7 quad-core (quando a janela do navegador é a única janela), que descobri que gostaria de poder acessar um temporizador de precisão de 0,1 ms em JavaScript, já que a precisão é finalmente agora lá em alguns sistemas de navegação de ponta para fazer com que a precisão do cronômetro valha a pena para certos tipos de aplicações de nicho que requerem alta precisão, e onde as aplicações são capazes de verificar se há desvios de precisão.
Obviamente, se você estiver fazendo várias passagens, pode simplesmente executar várias passagens (por exemplo, 10 passagens) e depois dividir por 10 para obter a precisão de 0,1 milissegundo. Esse é um método comum de obter melhor precisão - faça várias passagens e divida o tempo total pelo número de passagens.
NO ENTANTO ... Se eu puder fazer apenas uma única passagem de benchmark de um teste específico devido a uma situação incomumente única, descobri que posso obter 0,1 (e às vezes 0,01 ms) de precisão ao fazer isso:
Inicialização / calibração:
Comparação de uma passagem com precisão abaixo de um milissegundo:
AVISO: Loops ocupados NÃO são recomendados em navegadores da web, mas, felizmente, esses loops ocupados são executados por menos de 1 milissegundo cada, e são executados apenas algumas vezes.
Variáveis como compilação JIT e flutuações de CPU adicionam imprecisões massivas, mas se você executar várias passagens de inicialização, você terá recompilação dinâmica completa e, eventualmente, o contador se estabiliza em algo muito preciso. Certifique-se de que todos os loops ocupados tenham exatamente a mesma função para todos os casos, para que as diferenças nos loops ocupados não levem a diferenças. Certifique-se de que todas as linhas de código sejam executadas várias vezes antes de começar a confiar nos resultados, para permitir que os compiladores JIT já tenham se estabilizado para uma recompilação dinâmica completa (dynarec).
Na verdade, eu testemunhei uma precisão se aproximando de microssegundos em certos sistemas, mas eu não confiaria ainda. Mas a precisão de 0,1 milissegundo parece funcionar de forma bastante confiável, em um sistema quad-core ocioso onde sou a única página do navegador. Eu cheguei a um caso de teste científico em que eu só podia fazer passagens únicas (devido a variáveis únicas ocorrendo) e precisava cronometrar precisamente cada passagem, em vez de calcular a média de várias passagens repetidas, então é por isso que fiz isso.
Fiz vários pré-passes e passes fictícios (também para liquidar o dynarec), para verificar a confiabilidade da precisão de 0,1ms (permaneceu sólida por vários segundos), então mantive minhas mãos fora do teclado / mouse, enquanto o benchmark ocorria, então fiz vários pós-passes para verificar a confiabilidade da precisão de 0,1 ms (permaneceu sólido novamente). Isso também verifica se coisas como mudanças de estado de energia, ou outras coisas, não ocorreram entre o antes e o depois, interferindo nos resultados. Repita o pré-teste e o pós-teste entre cada passagem de benchmark. Com isso, eu estava quase certo de que os resultados intermediários eram precisos. Não há garantia, é claro, mas mostra que uma precisão precisa de <0,1 ms é possível em alguns casos em um navegador da web.
Este método só é útil em muito, muito nicho casos. Mesmo assim, literalmente não será 100% infinitamente garantível, você pode obter uma precisão bastante confiável e até mesmo uma precisão científica quando combinada com várias camadas de verificações internas e externas.
fonte
Date.now()
ou+new Date()
. Mas agora temosperformance.now()
. Embora esteja claro que você encontrou algumas maneiras interessantes de hackear mais recursos, esta resposta é essencialmente obsoleta. Além disso, não recomende nada relacionado a loops ocupados. Só não faça isso. Não precisamos mais disso.A resposta é "não", em geral. Se você estiver usando JavaScript em algum ambiente do lado do servidor (ou seja, não em um navegador), todas as apostas estão canceladas e você pode tentar fazer o que quiser.
editar - esta resposta é antiga; os padrões progrediram e novas instalações estão disponíveis como soluções para o problema da hora exata. Mesmo assim, deve ser lembrado que fora do domínio de um verdadeiro sistema operacional em tempo real, o código comum não privilegiado tem controle limitado sobre seu acesso aos recursos de computação. Medir o desempenho não é o mesmo (necessariamente) que prever o desempenho.
fonte
Aqui está um exemplo que mostra meu cronômetro de alta resolução para node.js :
Uso:
Normalmente, você pode usar:
Se você estiver cronometrando seções de código que envolvem loop, não poderá obter acesso ao valor de
console.timeEnd()
para adicionar os resultados do cronômetro. Você pode, mas fica desagradável porque você tem que injetar o valor de sua variável de iteração, comoi
, e definir uma condição para detectar se o loop está concluído.Aqui está um exemplo porque pode ser útil:
Cite: https://nodejs.org/api/process.html#process_process_hrtime_time
fonte