Packages

Get CSV from your benchee benchmarks to turn them into graphs or whatever!

Current section

Files

Jump to
benchee_csv lib benchee formatters csv.ex
Raw

lib/benchee/formatters/csv.ex

defmodule Benchee.Formatters.CSV do
use Benchee.Formatter
alias Benchee.Utility.FileCreation
alias Benchee.{Suite, Configuration}
alias Benchee.Formatters.CSV.{Statistics, Raw, Util}
@moduledoc """
Functionality for converting Benchee benchmarking results to CSV so that
they can be written to file and opened in a spreadsheet tool for graph
generation for instance.
The most basic use case is to configure it as one of the formatters to be
used by `Benchee.run/2`.
Benchee.run(
%{
"flat_map" => fn -> Enum.flat_map(list, map_fun) end,
"map.flatten" => fn -> list |> Enum.map(map_fun) |> List.flatten end
},
formatters: [
&Benchee.Formatters.CSV.output/1,
&Benchee.Formatters.Console.output/1
],
formatter_options: [csv: %[file: "my.csv"]]
)
"""
@doc """
Transforms the statistical results `Benche.statistics` to be written
somewhere, such as a file through `IO.write/2`.
## Examples
iex> suite = %Benchee.Suite{
...> scenarios: [
...> %Benchee.Benchmark.Scenario{
...> name: "My Job",
...> run_times: [500],
...> input_name: "Some Input",
...> input: "Some Input",
...> run_time_statistics: %Benchee.Statistics{
...> average: 500.0,
...> ips: 2000.0,
...> std_dev: 200.0,
...> std_dev_ratio: 0.4,
...> std_dev_ips: 800.0,
...> median: 450.0,
...> minimum: 200,
...> maximum: 900,
...> sample_size: 8
...> }
...> }
...> ],
...> configuration: %Benchee.Configuration{
...> formatter_options: %{csv: %{file: "my_file.csv"}}
...> }
...> }
iex> suite
iex> |> Benchee.Formatters.CSV.format
iex> |> Enum.fetch!(0)
iex> |> (fn({rows, _}) -> Enum.take(rows, 2) end).()
["Name,Input,Iterations per Second,Average,Standard Deviation,Standard Deviation Iterations Per Second,Standard Deviation Ratio,Median,Minimum,Maximum,Sample Size\\r\\n",
"My Job,Some Input,2.0e3,500.0,200.0,800.0,0.4,450.0,200,900,8\\r\\n"]
"""
@spec format(Suite.t) :: [{Enumerable.t, String.t}]
def format(%Suite{scenarios: scenarios, configuration: configuration}) do
sorted_scenarios = Enum.sort_by(scenarios, fn(scenario) -> scenario.input_name end)
filename = get_filename(configuration)
[
{get_benchmarks_statistics(sorted_scenarios), filename},
{get_benchmarks_raw(sorted_scenarios), FileCreation.interleave(filename, "raw")}
]
end
defp get_benchmarks_statistics(scenarios) do
scenarios
|> Enum.map(&Statistics.to_csv/1)
|> Statistics.add_headers()
|> CSV.encode()
end
defp get_benchmarks_raw(scenarios) do
scenarios
|> Enum.map(fn scenario -> scenario.run_times end)
|> Util.zip_all
|> Raw.add_headers(scenarios)
|> CSV.encode()
end
@default_filename "benchmark_output.csv"
defp get_filename(%Configuration{formatter_options: %{csv: %{file: filename}}}), do: filename
defp get_filename(_configuration), do: @default_filename
@doc """
Uses the return value of `Benchee.Formatters.CSV.format/1` to write the
statistics output to a CSV file, defined in the initial
configuration under `[formatter_options: [csv: [file: \"my.csv\"]]`.
If file is not defined then output is going to be placed in
"benchmark_output.csv". All raw measurements are placed in raw_benchmark_output.csv.
"""
@spec write([{Enumerable.t, String.t}]) :: :ok
def write(benchmarks) do
Enum.each(benchmarks, fn({content, filename}) -> write(content, filename) end)
end
defp write(content, filename) do
File.open filename, [:write, :utf8], fn(file) ->
Enum.each(content, fn(row) -> IO.write(file, row) end)
end
IO.puts "CSV written to #{filename}"
end
end