Quanto tempo uma dada função demora entre seu disparo e o output?

Olá pessoal,

Como apurar o tempo (em milissegundos, p ex.) consumido para se executar uma dada função?

É que estou construindo um shinyApp e pra fins de celeridade ao usuário final, desejava comparar o tempo consumido entre as diferentes formas de implementar um cálculo, uma transformação, uma busca, etc.

Obrigado,
Humberto

Eu costumo usar o pacote tictoc para ver o tempo que algum trecho de código demora. Ah, e para executar, eu seleciono desde o tic até o toc para conseguir medir desde o início até o final. Ex:

# inicia o contador no tic
tictoc::tic()
# o seu codigo aqui
Sys.sleep(3) # esse codigo de exemplo vai fazer o R esperar 3 segundos
# termina o contador no toc
tictoc::toc()
#> 3.009 sec elapsed

Created on 2022-04-05 by the reprex package (v2.0.1)

3 Curtidas

No blog da Curso-R acabei descobrindo a função system.time()

Eu gostei do fato de ela cravar o exato tempo colocado na instrução, ex:

 system.time({ Sys.sleep(time = 3) })

#>  usuário   sistema decorrido 
        0         0         3 

Possivelmente a função tictoc::toc() consumiu alguns milissegundos em suas próprias rotinas

Entretanto, ao colocarmos para system.time() esse tempo retornado pelo toc(), 3,009 segundos, também teremos um resultado um tanto inexato:

 system.time({Sys.sleep(time = 3.009)})
  usuário   sistema decorrido 
#>     0.00      0.00      3.02 

Desconfio que ele “arredonde” o parâmetro de entrada para duas casas, consumindo alguns milissegundos nisso. Gostei das duas funções, mas me identifiquei com a função toc() pois me lembra que minha preocupação com milissegundos exatos pode ser t.o.c. :sweat_smile:

Vim me intrometer só para explicar o resultado “inexato” da system.time(). Na verdade, o problema é com a Sys.sleep()! De acordo com a documentação (negritos meus):

There is no guarantee that the process will sleep for the whole of the specified interval (sleep might be interrupted), and it may well take slightly longer in real time to resume execution.

time must be non-negative (and not NA nor NaN): Inf is allowed (and might be appropriate if the intention is to wait indefinitely for an interrupt). The resolution of the time interval is system-dependent, but will normally be 20ms or better. (On modern Unix-alikes it will be better than 1ms.)

Ou seja, a Sys.sleep() não garante que ela irá esperar exatamente o tempo que você pediu e a resolução dos intervalos de tempo gira em torno de 20ms. Note que o tempo decorrido pulou de 3s no primeiro exemplo para 3.02s no segundo, exatamente 20ms de diferença :wink: Não é coincidência.


P.S.: Sobre a sua preocupação com milissegundos, @hal-delaserna, eu não acho que seja inteiramente equivocada. Normalmente não somos capazes de notar ganhos desse tamanho, mas os atrasos acumulam… Uma tarefa de 1 segundo repetida 1000 vezes totaliza quase 20 minutos; reduzir um programa de 1 segundo para 0.5 é pouco, mas de 20 minutos para 10 já é outra história.

Tem um vídeo curtinho na internet de uma palestra ministrada pela Grace Hopper, uma das grandes pioneiras da computação. Nele, ela mostra a diferença entre 1 microssegundo e 1 nanossegundo (respectivamente 1 mil e 1 milhão de vezes menos que 1 milissegundo) e sugere que todo programador tenha 1 microssegundo pendurado ao lado de seu computador. Eu ainda não tenho o meu, mas esse vídeo mudou minha perspectiva sobre quanto tempo jogamos fora ao fazer um programa ineficiente.

2 Curtidas

Olá Caio, valeu pela interessante explicação. Outra aplicação bem sensível a tais escalas minúsculas de tempo deve estar, acredito eu, em plataformas de trading e criptomoedas. Jogos on line tmb

1 Curtida