crystal-lang / crystal

The Crystal Programming Language
https://crystal-lang.org
Apache License 2.0
19.2k stars 1.61k forks source link

Customizing or hiding `Benchmark.ips`'s output format #14738

Open HertzDevil opened 1 week ago

HertzDevil commented 1 week ago

Benchmark.ips always prints its result to STDOUT in a nicely formatted table:

Benchmark.ips do |b|
  b.report("foo") { Array.new(1000, 0) }
  b.report("bar") { Array.new(5000, 0) }
end
foo   2.33M (429.67ns) (± 1.14%)  3.96kB/op        fastest
bar 906.57k (  1.10µs) (± 0.81%)  19.5kB/op   2.57× slower

But often I want to use those numbers somewhere else, e.g. plotting a graph, and to avoid parsing the above table again, I take the returned Benchmark::IPS::Job (the docs don't really mention this) and post-process the items into a JSON:

ips = Benchmark.ips { ... }
j = JSON.build do |json|
  json.object do
    json.field "items" do
      json.array do
        ips.items.each do |item|
          json.object do
            json.field "label", item.label
            json.field "mean", item.mean
            json.field "stddev", item.stddev
            json.field "bytes_per_op", item.bytes_per_op
          end
        end
      end
    end
  end
end

IMO this is still not straightforward enough, because I don't want to pollute STDOUT at all. It would be nice if Benchmark.ips itself supports those alternative formats out of the box. So I suggest implementing any of the following:

Similar points probably hold for Benchmark.bm as well.

yxhuvud commented 1 week ago

I slightly question the exposure of raw Array(IPS::Entry) rather than something that would allow a replacement of the inner structures.

That said it would be really cool if it were easier to export it to hdr histogram format so that it can be put into plotter .

HertzDevil commented 1 week ago

Benchmark::IPS::Entry is "public" insofar as it isn't marked as :nodoc:. Indeed a lot of things under Benchmark should have been protected or hidden.

ran_items is always a fresh Array, but the entries themselves are mutable and have reference semantics, so perhaps they have to be duplicated.

straight-shoota commented 1 week ago

I like the reporter pattern. It enables different formats.