在没有 Benchmark 或 time 的情况下测量 Ruby 中的用户时间或系统时间

发布于 2024-11-15 21:10:11 字数 470 浏览 7 评论 0原文

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

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

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

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

多谢!

Since I'm doing some time measurements at the moment, I wondered if it is possible to measure the user time or system time without using the Benchmark class or the command line utility time.

Using the Time class only reveals the wall clock time, not system and user time, however I'm looking for a solution which has the same flexibility, e.g.

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

The reason is that I somehow dislike Benchmark, since it cannot return numbers only (EDIT: I was wrong - it can. See answers below.). Sure, I could parse the output, but that doesn't feels right. The time utility from *NIX systems should solve my problem as well, but I wanted to know if there already is some kind of wrapper implemented in Ruby so I don't need to make these system calls by myself.

Thanks a lot!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

情深如许 2024-11-22 21:10:11

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

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

在这个过程中一样简单,我发现你可以添加自定义行基准输出。您可以使用它来获得两全其美的效果(自定义时间测量和最后的良好输出),如下所示:

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)

I re-read the Benchmark documentation and saw that it has a method named measure. This method does exactly what I want: Measure the time your code needs and returning an object which contains user time, system time, system time of childrens etc. It is as easy as

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

In the process I found out that you can add custom rows to the Benchmark output. You can use this to get the best of both worlds (custom time measurements and a nice output at the end) as follows:

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

The result will look like the following:

             user     system      total        real
sum:     2.700000   0.000000   2.700000 (  2.706234)
avg:     0.270000   0.000000   0.270000 (  0.270623)
半衾梦 2024-11-22 21:10:11

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

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

You could use the Process::times function, which returns user time/system time. (It does not report wall clock time, you'll need something else for that). Seems to be a bit version or OS dependent though.

This is what it reports on my system (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>

The docs show this though, so some versions/implementations might only have the first two:

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

See times for the underlying call on Linux.

Here's a really crappy wrapper that kind of supports -:

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

Should give you ideas to make it work nicely in your context.

心病无药医 2024-11-22 21:10:11

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

不再有这样的代码:

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

现在你可以这样做:

benchmark :calculate_report # in class

并且只需调用你的方法

user.calculate_report

This gem might help:
https://github.com/igorkasyanchuk/benchmark_methods

No more code like this:

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

Now you can do:

benchmark :calculate_report # in class

And just call your method

user.calculate_report
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文