Pergunta

Já que estou fazendo algumas medições de tempo no momento, gostaria de saber se é possível medir o tempo do usuário ou do sistema sem usar a classe Benchmark ou o utilitário de linha de comando time.

Usar a classe Time revela apenas a hora do relógio de parede, não a hora do sistema e do usuário. No entanto, estou procurando uma solução que tenha a mesma flexibilidade, por exemplo,

time = TimeUtility.now
# some code
user, system, real = TimeUtility.now - time

A razão é que, de alguma forma, não gosto de Benchmark, uma vez que não pode retornar apenas números ( EDIT: Eu estava errado - pode. Veja as respostas abaixo. ).Claro, eu poderia analisar a saída, mas não parece certo.O utilitário time dos sistemas * NIX deve resolver meu problema também, mas eu queria saber se já existe algum tipo de wrapper implementado em Ruby, então não preciso fazer essas chamadas de sistema sozinho.

Muito obrigado!

Foi útil?

Solução

Eu reli a documentação do Benchmark e vi que ela tem um método chamado measure.Este método faz exatamente o que eu quero: medir o tempo que seu código precisa e retornar um objeto que contém a hora do usuário, a hora do sistema, a hora do sistema das crianças, etc. É tão fácil quanto

require 'benchmark'
measurement = Benchmark.measure do
  # your code goes here
end

No processo, descobri que você pode adicionar linhas personalizadas à saída do Benchmark.Você pode usar isso para obter o melhor dos dois mundos (medições de tempo personalizadas e uma boa saída no final) da seguinte maneira:

require 'benchmark'

measurements = []
10.times { measurements << Benchmark.measure { 1_000_000.times { a = "1" } } }

# measurements.sum or measurements.inject(0){...} does not work, since the
# array contains Benchmark instances, which cannot be coerced into Fixnum's
# Array#sum will work if you are using Rails
sum = measurements.inject(nil) { |sum, t| sum.nil? ? sum = t : sum += t }
avg = sum / measurements.size

# 7 is the width reserved for the description "sum:" and "avg:"
Benchmark.bm(7, "sum:", "avg:") do |b|
  [sum, avg]
end

O resultado será semelhante ao seguinte:

             user     system      total        real
sum:     2.700000   0.000000   2.700000 (  2.706234)
avg:     0.270000   0.000000   0.270000 (  0.270623)

Outras dicas

Você pode usar a função Process::times , que retorna o usuáriohora / hora do sistema.(Ele não informa o tempo do relógio de parede, você precisará de algo mais para isso).Parece ser um pouco dependente da versão ou do sistema operacional.

Isso é o que relata no meu sistema (linux, ruby 1.8.7):

$ irb
irb(main):001:0> t = Process.times
=> #<struct Struct::Tms utime=0.01, stime=0.0, cutime=0.0, cstime=0.0>

Os documentos mostram isso, portanto, algumas versões / implementações podem ter apenas as duas primeiras:

t = Process.times
[ t.utime, t.stime ]   #=> [0.0, 0.02]

Consulte times para ochamada subjacente no Linux.

Este é um invólucro realmente ruim que suporta -:

class SysTimes

    attr_accessor :user, :system

    def initialize
        times = Process.times
        @user = times.utime
        @system = times.stime
    end

    def -(other)
        diff = SysTimes.new
        diff.user = @user - other.user
        diff.system = @system - other.system
        diff
    end
end

Deve dar ideias para fazer funcionar bem no seu contexto.

Esta joia pode ajudar: https://github.com/igorkasyanchuk/benchmark_methods

Não há mais código como este:

t = Time.now
user.calculate_report
puts Time.now - t

Agora você pode fazer:

benchmark :calculate_report # in class

E apenas chame seu método

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