0

I have a benchmark like follows:

benchmark_result = Benchmark.bm do |x|
  x.report { send(test_name) }
end

When I run this, I'm seeing output from two places:

  1. The send(test_name) in the report block. I want to continue seeing this output.
  2. The output from the Benchmark block, i.e. the resulting benchmark report is printed to the console. I don't want this to happen.

I've seen from here how to temporarily hide the console output. But the problem is that I want the inner block to continue printing its output. I just don't want to see the benchmark results.

Community
  • 1
  • 1
max pleaner
  • 26,189
  • 9
  • 66
  • 118
  • 2
    You want to see the output from the method calls but *not* show the benchmark output? I'm not sure why you'd benchmark something and then throw out the results. – tadman May 01 '16 at 17:00
  • 1
    I'm making a 'benchmark caching' system so that when I request a benchmark for a method, I don't have to actually run the method again. This is specifically for long-running methods and I recognize that the results will not be completely accurate. People told me this numerous times on my recently posted question [here](http://stackoverflow.com/questions/36961017/how-to-multiply-a-benchmark?noredirect=1#comment61480374_36961017). Basically, whenever I run a test case I'm storing the benchmark, which is displayed at a later time. – max pleaner May 01 '16 at 17:22
  • An interesting project, thanks for explaining. I think AmitA's approach where you can capture the results and save them in some manner for later use is best. You could actually put these in some small database, like SQLite, to organize them better if necessary. – tadman May 02 '16 at 00:24

2 Answers2

3

When you call the report method on the Benchmark::Report object sent to the block by Benchmark.bm or Benchmark.benchmark, it will print to STDOUT. If you're just interested in the benchmark metrics without printing a report, you can do this:

benchmark_result = Benchmark.measure do
  send(test_name) 
end

It returns a Benchmark::Tms object that looks like this:

 => #<Benchmark::Tms:0x007fb5b1b40118
 @cstime=0.0,
 @cutime=0.0,
 @label="",
 @real=4.5693013817071915e-05,
 @stime=0.0,
 @total=0.0,
 @utime=0.0>

If you're just interested in the elapsed real time used to execute your block, do the following (returns a Float):

benchmark_result = Benchmark.realtime do
  send(test_name) 
end
AmitA
  • 3,239
  • 1
  • 22
  • 31
  • 1
    I've used `Benchmark` many times, but never actually read the [doc](http://ruby-doc.org/stdlib-2.3.0/libdoc/benchmark/rdoc/Benchmark.html). Not a bad idea. – Cary Swoveland May 01 '16 at 19:25
0

I've accepted Amit's answer because it seems canonical, but I did figure out another way to do it in the meantime.

From this question I have added the following code (slightly modified to include the touch/rm calls on the null.txt file):

def silence_output
  # Store the original stderr and stdout in order to restore them later
  @original_stderr = $stderr
  @original_stdout = $stdout

  # Redirect stderr and stdout
  `touch null.txt`
  $stderr = File.new(File.join(File.dirname(__FILE__), 'null.txt'), 'w')
  $stdout = File.new(File.join(File.dirname(__FILE__), 'null.txt'), 'w')
end

# Replace stderr and stdout so anything else is output correctly
def enable_output
  $stderr = @original_stderr
  $stdout = @original_stdout
  @original_stderr = nil
  @original_stdout = nil
  `rm null.txt`
end

With this, I can accomplish my goal using the following:

silence_output
benchmark_result = Benchmark.bm do |x|
  x.report do   
    enable_output
    send(test_name)
    silence_output
  end
end
enable_output

Although after seeing a better way to do it, this seems very hacky.

Community
  • 1
  • 1
max pleaner
  • 26,189
  • 9
  • 66
  • 118