Como obtenho o tempo decorrido em milissegundos no Ruby?


98

Se eu tiver um Timeobjeto obtido de:

Time.now

e depois instanciar outro objeto com essa mesma linha, como posso ver quantos milissegundos se passaram? O segundo objeto pode ser criado no mesmo minuto, ao longo dos próximos minutos ou mesmo horas.

Respostas:


133

Como já foi dito, você pode operar em Timeobjetos como se fossem valores numéricos (ou de ponto flutuante). Essas operações resultam em uma segunda resolução, que pode ser facilmente convertida.

Por exemplo:

def time_diff_milli(start, finish)
   (finish - start) * 1000.0
end

t1 = Time.now
# arbitrary elapsed time
t2 = Time.now

msecs = time_diff_milli t1, t2

Você precisará decidir se deve truncar ou não.


2
adicione um to_i e você o terá como um inteiro, por exemplo: ((terminar - iniciar) * 1000.0) .to_i
Travis Reeder

finish.to_f - start.to_f?
bodacious

1
finish - startproduz ponto flutuante; .to_fseria redundante.
ezpz

5
Se estiver usando trilhos ou suporte ativo, você pode usar o método #in_milliseconds para fazer a mesma conversão(t2 - t1).in_milliseconds
Nathan Hanna,

58

Você pode adicionar um pouco de açúcar sintático à solução acima com o seguinte:

class Time
  def to_ms
    (self.to_f * 1000.0).to_i
  end
end

start_time = Time.now
sleep(3)
end_time = Time.now
elapsed_time = end_time.to_ms - start_time.to_ms  # => 3004

31

Acho que a resposta foi escolhida incorretamente, esse método dá segundos, não milissegundos.

t = Time.now.t­o_f
=> 1382471965.146

Aqui, suponho que o valor flutuante são os milissegundos


1
A resposta escolhida está correta. Usar adição ou subtração Time.nowé tratar o tempo como valores de ponto flutuante com segundos antes do ponto decimal e até nanossegundos após o ponto decimal (embora nsec possa não ser completamente preciso). Portanto, a multiplicação desse valor por 1000.0resulta em milissegundos.
dfherr

sim, mas fornecer apenas "Time.now" é incorreto e não responde à pergunta com precisão.
LowFieldTheory

12

Para obter o tempo em milissegundos, é melhor adicionar .round(3), para que seja mais preciso em alguns casos:

puts Time.now.to_f # => 1453402722.577573

(Time.now.to_f.round(3)*1000).to_i  # => 1453402722578

9

A resposta do ezpz é quase perfeita, mas espero poder acrescentar um pouco mais.

Geo perguntou sobre o tempo em milissegundos; isso soa como uma quantidade inteira, e eu não faria o desvio por terra de ponto flutuante. Portanto, minha abordagem seria:

irb(main):038:0> t8 = Time.now
=> Sun Nov 01 15:18:04 +0100 2009
irb(main):039:0> t9 = Time.now
=> Sun Nov 01 15:18:18 +0100 2009
irb(main):040:0> dif = t9 - t8
=> 13.940166
irb(main):041:0> (1000 * dif).to_i
=> 13940

Multiplicar por um inteiro 1000 preserva o número fracionário perfeitamente e pode ser um pouco mais rápido também.

Se estiver lidando com datas e horas, pode ser necessário usar a classe DateTime . Isso funciona de forma semelhante, mas o fator de conversão é 24 * 3600 * 1000 = 86400000 .

Eu encontrei de DateTime strptime e strftime funções de valor inestimável na análise e formatação de seqüências de data / hora (por exemplo, para / de registros). O que é útil saber é:

  • Os caracteres de formatação para essas funções (% H,% M,% S, ...) são quase os mesmos que para as funções C encontradas em qualquer sistema Unix / Linux; e

  • Existem mais alguns: Em particular, % L faz milissegundos!


Bom saber! Obrigado unknown:)
Geo

1
De qualquer forma,% L existe apenas em Ruby 1.9;)
Rafa de Castro

7
DateTime.now.strftime("%Q")

Exemplo de uso:

>> DateTime.now.strftime("%Q")
=> "1541433332357"

>> DateTime.now.strftime("%Q").to_i
=> 1541433332357

6

Time.now.to_f pode ajudá-lo, mas retorna segundos.

Em geral, ao trabalhar com benchmarks I:

  • põe na variável a hora atual;
  • insira o bloco para testar;
  • coloque em uma variável a hora atual, subtraindo o valor da hora atual anterior;

É um processo muito simples, então não tenho certeza se você estava realmente perguntando isso ...


6

%L dá milissegundos em rubi

require 'time'
puts Time.now.strftime("%Y-%m-%dT%H:%M:%S.%L")

ou

puts Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")

fornecerá o carimbo de data / hora atual em milissegundos.


Isso não diz como obter o tempo decorrido.
Robert

4

A resposta é algo como:

t_start = Time.now
# time-consuming operation
t_end = Time.now

milliseconds = (t_start - t_end) * 1000.0

No entanto, a Time.nowabordagem corre o risco de ser imprecisa. Encontrei esta postagem de Luca Guidi:

https://blog.dnsimple.com/2018/03/elapsed-time-with-ruby-the-right-way/

o relógio do sistema está constantemente flutuando e não se move apenas para frente. Se o seu cálculo do tempo decorrido se basear nele, é muito provável que você se depare com erros de cálculo ou mesmo interrupções .

Portanto, é recomendável usar em seu Process.clock_gettimelugar. Algo como:

def measure_time
  start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
  yield
  end_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
  elapsed_time = end_time - start_time
  elapsed_time.round(3)
end

Exemplo:

elapsed = measure_time do
    # your time-consuming task here:
    sleep 2.2321
end

=> 2.232

3

Tente subtrair o primeiro Time.now do segundo. Igual a:

a = Time.now
sleep(3)
puts Time.now - a # about 3.0

Isso dá a você um número de ponto flutuante dos segundos entre os dois tempos (e com isso, os milissegundos).

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.