diff --git a/lib/benchee/conversion/count.ex b/lib/benchee/conversion/count.ex index fe2b95fa..d25cec2a 100644 --- a/lib/benchee/conversion/count.ex +++ b/lib/benchee/conversion/count.ex @@ -14,7 +14,7 @@ defmodule Benchee.Conversion.Count do @one_million 1_000_000 @one_thousand 1_000 - @units %{ + @units_map %{ billion: %Unit{ name: :billion, magnitude: @one_billion, @@ -41,6 +41,8 @@ defmodule Benchee.Conversion.Count do } } + @units Map.values(@units_map) + @type unit_atoms :: :one | :thousand | :million | :billion @type units :: unit_atoms | Unit.t() @@ -111,7 +113,11 @@ defmodule Benchee.Conversion.Count do } """ def unit_for(unit) do - Scale.unit_for(@units, unit) + Scale.unit_for(@units_map, unit) + end + + def units do + @units end @doc """ @@ -191,8 +197,9 @@ defmodule Benchee.Conversion.Count do def base_unit, do: unit_for(:one) @doc """ - Formats a number as a string, with a unit label. To specify the unit, pass - a tuple of `{value, unit_atom}` like `{1_234, :million}` + Formats a number as a string, with a unit label. + + To specify the unit, pass a tuple of `{value, unit_atom}` like `{1_234, :million}` ## Examples @@ -211,4 +218,22 @@ defmodule Benchee.Conversion.Count do def format(count) do Format.format(count, __MODULE__) end + + @doc """ + Formats in a more "human" way separating by units. + + ## Examples + + iex> format_human(45_678.9) + "45 K 678.90" + + iex> format_human(1_000_000) + "1 M" + + iex> format_human(1_001_000) + "1 M 1 K" + """ + def format_human(count) do + Format.format_human(count, __MODULE__) + end end diff --git a/lib/benchee/conversion/deviation_percent.ex b/lib/benchee/conversion/deviation_percent.ex index e79d72f7..355a6b93 100644 --- a/lib/benchee/conversion/deviation_percent.ex +++ b/lib/benchee/conversion/deviation_percent.ex @@ -11,9 +11,10 @@ defmodule Benchee.Conversion.DeviationPercent do @behaviour Format @doc """ - Formats the standard deviation ratio to an equivalent percent number - including special signs. The ± is an important part of it as it shows that - the deviation might be up but also might be down. + Formats the standard deviation ratio to an equivalent percent number including special signs. + + The ± is an important part of it as it shows that the deviation might be up but also might be + down. ## Examples @@ -28,4 +29,18 @@ defmodule Benchee.Conversion.DeviationPercent do |> :io_lib.format(["±", std_dev_ratio * 100.0]) |> to_string end + + @doc """ + Formats standard deviation percent, same as `format/1`. + + Implemented for consistency. + + ## Examples + + iex> format_human(0.1) + "±10.00%" + """ + def format_human(std_dev_ratio) do + format(std_dev_ratio) + end end diff --git a/lib/benchee/conversion/duration.ex b/lib/benchee/conversion/duration.ex index 18eca721..45d58895 100644 --- a/lib/benchee/conversion/duration.ex +++ b/lib/benchee/conversion/duration.ex @@ -21,7 +21,7 @@ defmodule Benchee.Conversion.Duration do @nanoseconds_per_minute @nanoseconds_per_second * @seconds_per_minute @nanoseconds_per_hour @nanoseconds_per_minute * @minutes_per_hour - @units %{ + @units_map %{ hour: %Unit{ name: :hour, magnitude: @nanoseconds_per_hour, @@ -60,6 +60,8 @@ defmodule Benchee.Conversion.Duration do } } + @units Map.values(@units_map) + @doc """ Scales a duration value in nanoseconds into a larger unit if appropriate @@ -140,7 +142,7 @@ defmodule Benchee.Conversion.Duration do } """ def unit_for(unit) do - Scale.unit_for(@units, unit) + Scale.unit_for(@units_map, unit) end def units do @@ -268,20 +270,24 @@ defmodule Benchee.Conversion.Duration do end @doc """ - iex> format_human(5_400_000_000_000) - "1 h 30 min" + Formats in a more "human" way - 1h 30min instead of 1.5h. + + ## Examples + + iex> format_human(5_400_000_000_000) + "1 h 30 min" - iex> format_human(12.5) - "12.50 ns" + iex> format_human(12.5) + "12.50 ns" - iex> format_human(1000.555) - "1 μs 0.55 ns" + iex> format_human(1000.555) + "1 μs 0.55 ns" - iex> format_human(3_660_001_001_000) - "1 h 1 min 1 ms 1 μs" + iex> format_human(3_660_001_001_000) + "1 h 1 min 1 ms 1 μs" - iex> format_human(0) - "0 ns" + iex> format_human(0) + "0 ns" """ def format_human(duration) do Format.format_human(duration, __MODULE__) diff --git a/lib/benchee/conversion/format.ex b/lib/benchee/conversion/format.ex index 0be50aa8..acf1c6bb 100644 --- a/lib/benchee/conversion/format.ex +++ b/lib/benchee/conversion/format.ex @@ -14,24 +14,31 @@ defmodule Benchee.Conversion.Format do """ @callback format(number) :: String.t() + @doc """ + Formats in a more "human" way, one biggest unit at a time. + + So instead of 1.5h it says 1h 30min + """ + @callback format_human(number) :: String.t() + # Generic formatting functions @doc """ Formats a unit value with specified label and separator """ - def format(count, label, separator) do + def format(number, label, separator) do separator = separator(label, separator) - "#{number_format(count)}#{separator}#{label}" + "#{number_format(number)}#{separator}#{label}" end - defp number_format(count) when is_float(count) do - count - |> :erlang.float_to_list(decimals: float_precision(count)) + defp number_format(number) when is_float(number) do + number + |> :erlang.float_to_list(decimals: float_precision(number)) |> to_string end - defp number_format(count) when is_integer(count) do - to_string(count) + defp number_format(number) when is_integer(number) do + to_string(number) end @doc """ @@ -49,16 +56,16 @@ defmodule Benchee.Conversion.Format do "1 KB" """ - def format({count, unit = %Unit{}}) do - format(count, label(unit), separator()) + def format({number, unit = %Unit{}}) do + format(number, label(unit), separator()) end - def format({count, unit = %Unit{}}, _module) do - format({count, unit}) + def format({number, unit = %Unit{}}, _module) do + format({number, unit}) end - def format({count, unit_atom}, module) do - format({count, module.unit_for(unit_atom)}) + def format({number, unit_atom}, module) do + format({number, module.unit_for(unit_atom)}) end def format(number, module) when is_number(number) do @@ -96,9 +103,7 @@ defmodule Benchee.Conversion.Format do end defp units_descending(module) do - module.units() - |> Map.values() - |> Enum.sort(&(&1.magnitude >= &2.magnitude)) + Enum.sort(module.units(), &(&1.magnitude >= &2.magnitude)) end @spec place_values(number, [Unit.t()]) :: [{number, Unit.t()}] diff --git a/lib/benchee/conversion/memory.ex b/lib/benchee/conversion/memory.ex index a18a4319..72fa44d8 100644 --- a/lib/benchee/conversion/memory.ex +++ b/lib/benchee/conversion/memory.ex @@ -15,7 +15,7 @@ defmodule Benchee.Conversion.Memory do @bytes_per_gigabyte @bytes_per_megabyte * @bytes_per_kilobyte @bytes_per_terabyte @bytes_per_gigabyte * @bytes_per_kilobyte - @units %{ + @units_map %{ terabyte: %Unit{ name: :terabyte, magnitude: @bytes_per_terabyte, @@ -48,6 +48,8 @@ defmodule Benchee.Conversion.Memory do } } + @units Map.values(@units_map) + @type unit_atom :: :byte | :kilobyte | :megabyte | :gigabyte | :terabyte @type any_unit :: unit_atom | Unit.t() @@ -162,7 +164,11 @@ defmodule Benchee.Conversion.Memory do } """ def unit_for(unit) do - Scale.unit_for(@units, unit) + Scale.unit_for(@units_map, unit) + end + + def units do + @units end @doc """ @@ -225,8 +231,9 @@ defmodule Benchee.Conversion.Memory do def base_unit, do: unit_for(:byte) @doc """ - Formats a number as a string, with a unit label. To specify the unit, pass - a tuple of `{value, unit_atom}` like `{1_234, :kilobyte}` + Formats a memory as a string, with a unit label. + + To specify the unit, pass a tuple of `{value, unit_atom}` like `{1_234, :kilobyte}`. ## Examples @@ -249,4 +256,19 @@ defmodule Benchee.Conversion.Memory do def format(memory) do Format.format(memory, __MODULE__) end + + @doc """ + Formats in a more human way, where multiple units are used. + + ## Examples + + iex> format_human(45_678.9) + "44 KB 622.90 B" + + iex> format_human(1024 * 1024 * 1024) + "1 GB" + """ + def format_human(memory) do + Format.format_human(memory, __MODULE__) + end end diff --git a/lib/benchee/conversion/scale.ex b/lib/benchee/conversion/scale.ex index 24d74dee..14d85880 100644 --- a/lib/benchee/conversion/scale.ex +++ b/lib/benchee/conversion/scale.ex @@ -47,6 +47,11 @@ defmodule Benchee.Conversion.Scale do """ @callback unit_for(any_unit) :: unit + @doc """ + List of all the units supported by this type. + """ + @callback units :: [unit] + @doc """ Takes a tuple of a number and a unit and a unit to be converted to, returning the the number scaled to the new unit and the new unit.