【问题标题】:Measure user time or system time in Ruby without Benchmark or time在没有基准或时间的情况下在 Ruby 中测量用户时间或系统时间
【发布时间】:2011-06-17 05:16:32
【问题描述】:

由于我目前正在进行一些时间测量,我想知道是否可以在不使用Benchmark 类或命令行实用程序time 的情况下测量用户时间或系统时间。

使用Time 类只显示挂钟时间,而不是系统和用户时间,但是我正在寻找具有相同灵活性的解决方案,例如

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

原因是我不喜欢Benchmark,因为它不能只返回数字(编辑:我错了 - 它可以。请参阅下面的答案。)。当然,我可以解析输出,但感觉不对。 *NIX 系统中的time 实用程序也应该可以解决我的问题,但我想知道是否已经在 Ruby 中实现了某种包装器,所以我不需要自己进行这些系统调用。

非常感谢!

【问题讨论】:

    标签: ruby time benchmarking measurement systemtime


    【解决方案1】:

    我重新阅读了 Benchmark 文档,发现它有一个名为 measure 的方法。这个方法正是我想要的:测量你的代码需要的时间并返回一个包含用户时间、系统时间、儿童系统时间等的对象。就像

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

    在此过程中,我发现您可以将自定义行添加到 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)
    

    【讨论】:

    • 我只希望有require 'benchmark'; Benchmark.measure { ... }的快捷方式
    • 我不明白,引用的部分很短。你想要点什么? (允许伪代码;)
    • 当然,可能不能比这更短,只是在感叹 ruby​​ 缺少默认提供的一些快捷方式来节省打字。 + 我总是忘记是measurebmbmbm 还是别的什么:)
    【解决方案2】:

    您可以使用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
    

    应该给你一些想法,让它在你的环境中很好地工作。

    【讨论】:

    • 遗憾的是,它是一个不知道如何响应- 的结构,因此time = Process.times ; user, system = Process.times - time 会引发错误。但是,以前不知道这种方法,我喜欢这种方法,因为我可以查看我的程序在任何时间点运行了多长时间。 :) 感谢您的贡献!
    【解决方案3】:

    这颗宝石可能会有所帮助: https://github.com/igorkasyanchuk/benchmark_methods

    不再有这样的代码:

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

    现在你可以这样做了:

    benchmark :calculate_report # in class
    

    然后调用你的方法

    user.calculate_report
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-02-11
      • 1970-01-01
      • 2016-07-03
      • 2012-07-09
      • 2019-02-14
      • 1970-01-01
      • 2011-11-15
      • 1970-01-01
      相关资源
      最近更新 更多