From: "Eregon (Benoit Daloze)" Date: 2012-03-29T21:46:34+09:00 Subject: [ruby-core:43852] [ruby-trunk - Feature #5809] Benchmark#bm: remove the label_width parameter Issue #5809 has been updated by Eregon (Benoit Daloze). @naruse: Sorry, I meant to answer to your reply much earlier, I just didn't make my mind at that time. I understand the compatibility need, so I'll try to create a new method and refactor without changing existing API. So my goal is both to add a convenient method for formatting, using as much as possible what is already available, and refactor the existing code to avoid duplication where possible. Also, the example you gave is certainly worth investigating! I'll get back to this as soon as I can. ---------------------------------------- Feature #5809: Benchmark#bm: remove the label_width parameter https://bugs.ruby-lang.org/issues/5809#change-25361 Author: Eregon (Benoit Daloze) Status: Assigned Priority: Normal Assignee: naruse (Yui NARUSE) Category: lib Target version: Hello, I would like to keep on improving the benchmark library. Feature #4197 was mostly a clean-up, this intend to improve the existing methods. First, I would like to make Benchmark#bm smarter. I think than having to specify the maximum width of the labels as an argument is not natural, and probably not the best API. An easy way to calculate the maximum width is to store all blocks and labels and run them after the #bm block is yielded. That's the way #bmbm does it (although some people don't know #bmbm can calculate the width itself). It would also avoid the duplication between the Report and Job classes, and make #bm more consistent with #bmbm. There is however a good reason it is not done this way: It lets #report return immediately the Benchmark::Tms, which can then be assigned to a variable, and be used to easily display the total, average, etc: Benchmark.bm(7, ">total:", ">avg:") do |x| tf = x.report("for:") { for i in 1..n; a = "1"; end } tt = x.report("times:") { n.times do ; a = "1"; end } [tf+tt, (tf+tt)/3] end # => user system total real for: 0.000000 0.000000 0.000000 ( 0.000054) times: 0.000000 0.000000 0.000000 ( 0.000027) >total: 0.000000 0.000000 0.000000 ( 0.000081) >avg: 0.000000 0.000000 0.000000 ( 0.000027) I am not sure this is worth having to give the width. I think this feature is very rarely used (I actually never saw a code using it, except the code in the documentation). Please show me if I'm wrong. There are some workarounds. First, I made Benchmark#benchmark returns the times of the #reports (an Array of Tms). One can then easily store the results of #bm and print them (however it will not indent them automatically, but that could be fixed). tf,tt = Benchmark.bm { ... } puts ">total: #{(tf+tt)}" puts ">avg: #{(tf+tt)/3}" Second, it is actually possible to support the same feature, even when the #report blocks are executed after. This is done by creating "delay-able"/lazy objects, which remember the calls, and make the real calls by calling #compute on them. Benchmark#benchmark could then execute them when the #bm block is yielded, and it would be transparent to the user (except if he prints the result of #report inside the #bm block). The second is not small to implement, and might not belong to the benchmark library, but could be useful in general. It also adds some significant complexity. What do you think? -- http://bugs.ruby-lang.org/