Измерьте время пользователя или системное время в Ruby без эталона или времени - PullRequest
5 голосов
/ 17 июня 2011

Поскольку я сейчас делаю некоторые измерения времени, я подумал, можно ли измерить пользовательское или системное время без использования класса Benchmark или утилиты командной строки time.

Использование класса Time показывает только время настенных часов, а не системное и пользовательское время, однако я ищу решение с такой же гибкостью, например,

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

Причина в том, что мне почему-то не нравится Benchmark, поскольку он не может возвращать только цифры ( РЕДАКТИРОВАТЬ: я ошибся - может. См. Ответы ниже. ). Конечно, я могу разобрать вывод, но это не так. Утилита time из * NIX систем также должна решить мою проблему, но я хотел знать, есть ли уже какая-то оболочка, реализованная в Ruby, поэтому мне не нужно делать эти системные вызовы самостоятельно.

Большое спасибо!

Ответы [ 3 ]

8 голосов
/ 17 июня 2011

Я перечитал документацию Benchmark и увидел, что в ней есть метод с именем measure.Этот метод делает именно то, что я хочу: измерить время, необходимое вашему коду, и вернуть объект, который содержит пользовательское время, системное время, системное время детей и т. Д. Это так же просто, как

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

В процессе Iобнаружил, что вы можете добавить пользовательские строки в вывод Benchmark.Вы можете использовать это, чтобы получить лучшее из обоих миров (пользовательские измерения времени и хороший вывод в конце) следующим образом:

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

Результат будет выглядеть следующим образом:

             user     system      total        real
sum:     2.700000   0.000000   2.700000 (  2.706234)
avg:     0.270000   0.000000   0.270000 (  0.270623)
2 голосов
/ 17 июня 2011

Вы можете использовать функцию Process::times, которая возвращает время пользователя / системное время.(Он не сообщает время настенных часов, для этого вам понадобится что-то еще).Кажется, что она зависит от версии или ОС.

Это то, что она сообщает в моей системе (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>

Документы показывают это, так чтонекоторые версии / реализации могут иметь только первые две:

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

См. times для основного вызова в Linux.

Вот действительно дрянная оболочка такого родаопор -:

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

Должен дать вам идеи, чтобы он хорошо работал в вашем контексте.

0 голосов
/ 13 октября 2015

Этот камень может помочь: https://github.com/igorkasyanchuk/benchmark_methods

Код больше не похож на этот:

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

Теперь вы можете сделать:

benchmark :calculate_report # in class

И просто назовите свой метод

user.calculate_report
...