changed
CHANGELOG.md
|
@@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
7
|
|
8
|
+ ## 1.2.0 (2023-11-09)
|
9
|
+
|
10
|
+ Long time, huh? 😉 I'm not gonna repeat all that, but I'm happy benchee is in a place where it just works and doesn't need too much support. Biggest feature here is the implementation of the `Table.Reader` protocol for a better Livebook experience.
|
11
|
+
|
12
|
+ ### Features (User Facing)
|
13
|
+ * Trying to benchmark evaluated functions will now result in a warning. Thanks [@BrooklinJazz](https://github.com/BrooklinJazz), [@czrpb](https://github.com/czrpb), [@aar2dee2](https://github.com/aar2dee2),[@ReecesPeanutButterCodes](https://github.com/ReecesPeanutButterCodes).
|
14
|
+ * Add support for the [`Table.Reader`](https://hexdocs.pm/table/Table.html) protocol so that benchee works out of the box in Livebook. See [#369](https://github.com/bencheeorg/benchee/pull/369), big shoutout to [@akoutmos](https://github.com/akoutmos) and sorry for keeping it unreleased for so long.
|
15
|
+
|
16
|
+ ### Bugfixes (User Facing)
|
17
|
+ * Removed Elixir 1.16 compiler warnings around +0.0 and -0.0. Thanks [@tomciop](https://github.com/tomciopp).
|
18
|
+ * Building an escript and running it is fixed. See [#384](https://github.com/bencheeorg/benchee/issues/384) and thanks [@Munksgaard](https://github.com/Munksgaard)!
|
19
|
+
|
8
20
|
## 1.1.0 (2022-03-08)
|
9
21
|
|
10
22
|
Long time, huh? I'm sorry, combination of priorities, difficult to fix bugs, stress and arm problems kept me away too long.
|
|
@@ -14,8 +26,11 @@ This release brings major features long developed and now finally released (redu
|
14
26
|
* Reduction counting/measurements was implemented. Basically, it's a rather stable unit of execution implemented by the BEAM that measures in more abstract manner how much work was done. It's helpful, as it shouldn't be affected by load on the system. Check out [the docs](https://github.com/bencheeorg/benchee#measuring-reductions).
|
15
27
|
* You can now dive straight into profiling from your benchmarks by using the profiling feature. See [the docs](https://github.com/bencheeorg/benchee#profiling-after-a-run) - thanks [@pablocostass](https://github.com/pablocostass)
|
16
28
|
|
29
|
+ ### Default Behavior Changes (User Facing)
|
30
|
+ * measuring function call overhead is now turned off by default, as it only helps with extreme nano benchmarks and has some potential for causing wrong results, so it should only be opt in. We now also print out the measured overhead for vsibility.
|
31
|
+
|
17
32
|
### Bugfixes (User Facing)
|
18
|
- * Benchee now correctly looks for the time resolution as reported by `:erlang.system_info(:os_monotonic_time_source)` to accomodate when determining if a measurement is "precise" enough. Benche also works around an erlang bug we discovered present in erlang <= 22.2. [Issue for reference](https://github.com/bencheeorg/benchee/issues/313).
|
33
|
+ * Benchee now correctly looks for the time resolution as reported by `:erlang.system_info(:os_monotonic_time_source)` to accommodate when determining if a measurement is "precise" enough. Benche also works around an erlang bug we discovered present in erlang <= 22.2. [Issue for reference](https://github.com/bencheeorg/benchee/issues/313).
|
19
34
|
* The annoying stacktrace warning has been removed - thanks [@mad42](https://github.com/mad42)
|
20
35
|
|
21
36
|
### Noteworthy
|
changed
README.md
|
@@ -67,7 +67,7 @@ The aforementioned [plugins](#plugins) like [benchee_html](https://github.com/be
|
67
67
|
## Table of Contents
|
68
68
|
|
69
69
|
- [Features](#features)
|
70
|
- - [Statitics](#statitics)
|
70
|
+ - [Statistics](#statistics)
|
71
71
|
- [Installation](#installation)
|
72
72
|
- [Usage](#usage)
|
73
73
|
- [Configuration](#configuration)
|
|
@@ -104,7 +104,7 @@ The aforementioned [plugins](#plugins) like [benchee_html](https://github.com/be
|
104
104
|
|
105
105
|
* first runs the functions for a given warmup time without recording the results, to simulate a _"warm"/running_ system
|
106
106
|
* [measures memory usage](#measuring-memory-consumption)
|
107
|
- * provides you with lots of [statistics](#statitics)
|
107
|
+ * provides you with lots of [statistics](#statistics)
|
108
108
|
* plugin/extensible friendly architecture so you can use different formatters to display benchmarking results as [HTML, markdown, JSON and more](#plugins)
|
109
109
|
* measure not only [time](#measuring-time), but also measure [memory](#measuring-memory-consumption) and [reductions](#measuring-reductions)
|
110
110
|
* [profile](#profiling-after-a-run) right after benchmarking
|
|
@@ -115,7 +115,7 @@ The aforementioned [plugins](#plugins) like [benchee_html](https://github.com/be
|
115
115
|
* execute benchmark jobs in parallel to gather more results in the same time, or simulate a system under load
|
116
116
|
* well documented & well tested
|
117
117
|
|
118
|
- ### Statitics
|
118
|
+ ### Statistics
|
119
119
|
|
120
120
|
Provides you with the following **statistical data**:
|
121
121
|
|
|
@@ -146,7 +146,7 @@ end
|
146
146
|
|
147
147
|
Install via `mix deps.get` and then happy benchmarking as described in [Usage](#usage) :)
|
148
148
|
|
149
|
- Elixir versions supported/tested against are 1.6+. It _should_ theoretically still work with 1.4 & 1.5 but we don't actively test/support it.
|
149
|
+ Elixir versions supported/tested against are 1.7+. It _should_ theoretically still work with 1.4, 1.5 & 1.6 but we don't actively test/support it as installing them on current CI systems is not supported out of the box.
|
150
150
|
|
151
151
|
## Usage
|
152
152
|
|
|
@@ -338,7 +338,7 @@ Benchee.run(
|
338
338
|
%{
|
339
339
|
"something_great" => fn -> cool_stuff end
|
340
340
|
},
|
341
|
- memory_time: 2
|
341
|
+ reduction_time: 2
|
342
342
|
)
|
343
343
|
```
|
344
344
|
|
|
@@ -526,6 +526,8 @@ Enum."-map/2-lists^map/1-0-"/2 10001 26.38 2282 0.23
|
526
526
|
:lists.do_flatten/2 40001 57.24 4951 0.12
|
527
527
|
```
|
528
528
|
|
529
|
+ **Note about after_each hooks:** `after_each` hooks currently don't work when profiling a function, as they are not passed the return value of the function after the profiling run. It's already fixed on the elixir side and is waiting for release, likely in 1.14. It should then just work.
|
530
|
+
|
529
531
|
### Saving, loading and comparing previous runs
|
530
532
|
|
531
533
|
Benchee can store the results of previous runs in a file and then load them again to compare them. For example this is useful to compare what was recorded on the main branch against a branch with performance improvements.
|
changed
hex_metadata.config
|
@@ -1,63 +1,69 @@
|
1
|
- {<<"app">>,<<"benchee">>}.
|
2
|
- {<<"build_tools">>,[<<"mix">>]}.
|
3
|
- {<<"description">>,
|
4
|
- <<"Versatile (micro) benchmarking that is extensible. Get statistics such as:\naverage, iterations per second, standard deviation and the median.">>}.
|
5
|
- {<<"elixir">>,<<"~> 1.6">>}.
|
6
|
- {<<"files">>,
|
7
|
- [<<"lib">>,<<"lib/benchee.ex">>,<<"lib/benchee">>,
|
8
|
- <<"lib/benchee/scenario_loader.ex">>,
|
9
|
- <<"lib/benchee/relative_statistics.ex">>,<<"lib/benchee/scenario.ex">>,
|
10
|
- <<"lib/benchee/collection_data.ex">>,<<"lib/benchee/statistics.ex">>,
|
11
|
- <<"lib/benchee/system.ex">>,<<"lib/benchee/formatter.ex">>,
|
12
|
- <<"lib/benchee/formatters">>,<<"lib/benchee/formatters/tagged_save.ex">>,
|
13
|
- <<"lib/benchee/formatters/console.ex">>,
|
14
|
- <<"lib/benchee/formatters/console">>,
|
15
|
- <<"lib/benchee/formatters/console/reductions.ex">>,
|
16
|
- <<"lib/benchee/formatters/console/memory.ex">>,
|
17
|
- <<"lib/benchee/formatters/console/helpers.ex">>,
|
18
|
- <<"lib/benchee/formatters/console/run_time.ex">>,
|
19
|
- <<"lib/benchee/configuration.ex">>,<<"lib/benchee/profile.ex">>,
|
20
|
- <<"lib/benchee/conversion">>,<<"lib/benchee/conversion/duration.ex">>,
|
21
|
- <<"lib/benchee/conversion/format.ex">>,
|
22
|
- <<"lib/benchee/conversion/count.ex">>,
|
23
|
- <<"lib/benchee/conversion/memory.ex">>,<<"lib/benchee/conversion/unit.ex">>,
|
24
|
- <<"lib/benchee/conversion/deviation_percent.ex">>,
|
25
|
- <<"lib/benchee/conversion/scale.ex">>,<<"lib/benchee/benchmark.ex">>,
|
26
|
- <<"lib/benchee/conversion.ex">>,<<"lib/benchee/output">>,
|
27
|
- <<"lib/benchee/output/benchmark_printer.ex">>,
|
28
|
- <<"lib/benchee/output/profile_printer.ex">>,<<"lib/benchee/suite.ex">>,
|
29
|
- <<"lib/benchee/benchmark">>,<<"lib/benchee/benchmark/collect">>,
|
30
|
- <<"lib/benchee/benchmark/collect/reductions.ex">>,
|
31
|
- <<"lib/benchee/benchmark/collect/memory.ex">>,
|
32
|
- <<"lib/benchee/benchmark/collect/profile.ex">>,
|
33
|
- <<"lib/benchee/benchmark/collect/time.ex">>,
|
34
|
- <<"lib/benchee/benchmark/hooks.ex">>,
|
35
|
- <<"lib/benchee/benchmark/repeated_measurement.ex">>,
|
36
|
- <<"lib/benchee/benchmark/run_once.ex">>,
|
37
|
- <<"lib/benchee/benchmark/runner.ex">>,
|
38
|
- <<"lib/benchee/benchmark/scenario_context.ex">>,
|
39
|
- <<"lib/benchee/benchmark/function_call_overhead.ex">>,
|
40
|
- <<"lib/benchee/benchmark/collect.ex">>,<<"lib/benchee/utility">>,
|
41
|
- <<"lib/benchee/utility/parallel.ex">>,<<"lib/benchee/utility/repeat_n.ex">>,
|
42
|
- <<"lib/benchee/utility/erlang_version.ex">>,
|
43
|
- <<"lib/benchee/utility/file_creation.ex">>,
|
44
|
- <<"lib/benchee/utility/deep_convert.ex">>,<<".formatter.exs">>,
|
45
|
- <<"mix.exs">>,<<"README.md">>,<<"LICENSE.md">>,<<"CHANGELOG.md">>]}.
|
46
|
- {<<"licenses">>,[<<"MIT">>]}.
|
47
1
|
{<<"links">>,
|
48
2
|
[{<<"Blog posts">>,<<"https://pragtob.wordpress.com/tag/benchee/">>},
|
49
3
|
{<<"Changelog">>,<<"https://hexdocs.pm/benchee/changelog.html">>},
|
50
4
|
{<<"GitHub">>,<<"https://github.com/bencheeorg/benchee">>}]}.
|
51
5
|
{<<"name">>,<<"benchee">>}.
|
6
|
+ {<<"version">>,<<"1.2.0">>}.
|
7
|
+ {<<"description">>,
|
8
|
+ <<"Versatile (micro) benchmarking that is extensible. Get statistics such as:\naverage, iterations per second, standard deviation and the median.">>}.
|
9
|
+ {<<"elixir">>,<<"~> 1.6">>}.
|
10
|
+ {<<"app">>,<<"benchee">>}.
|
11
|
+ {<<"licenses">>,[<<"MIT">>]}.
|
52
12
|
{<<"requirements">>,
|
53
|
- [[{<<"app">>,<<"deep_merge">>},
|
54
|
- {<<"name">>,<<"deep_merge">>},
|
13
|
+ [[{<<"name">>,<<"table">>},
|
14
|
+ {<<"app">>,<<"table">>},
|
15
|
+ {<<"optional">>,true},
|
16
|
+ {<<"requirement">>,<<"~> 0.1.0">>},
|
17
|
+ {<<"repository">>,<<"hexpm">>}],
|
18
|
+ [{<<"name">>,<<"deep_merge">>},
|
19
|
+ {<<"app">>,<<"deep_merge">>},
|
55
20
|
{<<"optional">>,false},
|
56
|
- {<<"repository">>,<<"hexpm">>},
|
57
|
- {<<"requirement">>,<<"~> 1.0">>}],
|
58
|
- [{<<"app">>,<<"statistex">>},
|
59
|
- {<<"name">>,<<"statistex">>},
|
21
|
+ {<<"requirement">>,<<"~> 1.0">>},
|
22
|
+ {<<"repository">>,<<"hexpm">>}],
|
23
|
+ [{<<"name">>,<<"statistex">>},
|
24
|
+ {<<"app">>,<<"statistex">>},
|
60
25
|
{<<"optional">>,false},
|
61
|
- {<<"repository">>,<<"hexpm">>},
|
62
|
- {<<"requirement">>,<<"~> 1.0">>}]]}.
|
63
|
- {<<"version">>,<<"1.1.0">>}.
|
26
|
+ {<<"requirement">>,<<"~> 1.0">>},
|
27
|
+ {<<"repository">>,<<"hexpm">>}]]}.
|
28
|
+ {<<"files">>,
|
29
|
+ [<<"lib">>,<<"lib/benchee">>,<<"lib/benchee/conversion.ex">>,
|
30
|
+ <<"lib/benchee/scenario.ex">>,<<"lib/benchee/suite.ex">>,
|
31
|
+ <<"lib/benchee/configuration.ex">>,<<"lib/benchee/formatter.ex">>,
|
32
|
+ <<"lib/benchee/system.ex">>,<<"lib/benchee/profile.ex">>,
|
33
|
+ <<"lib/benchee/conversion">>,<<"lib/benchee/conversion/memory.ex">>,
|
34
|
+ <<"lib/benchee/conversion/unit.ex">>,
|
35
|
+ <<"lib/benchee/conversion/duration.ex">>,
|
36
|
+ <<"lib/benchee/conversion/scale.ex">>,<<"lib/benchee/conversion/count.ex">>,
|
37
|
+ <<"lib/benchee/conversion/deviation_percent.ex">>,
|
38
|
+ <<"lib/benchee/conversion/format.ex">>,<<"lib/benchee/utility">>,
|
39
|
+ <<"lib/benchee/utility/deep_convert.ex">>,
|
40
|
+ <<"lib/benchee/utility/repeat_n.ex">>,<<"lib/benchee/utility/parallel.ex">>,
|
41
|
+ <<"lib/benchee/utility/erlang_version.ex">>,
|
42
|
+ <<"lib/benchee/utility/file_creation.ex">>,
|
43
|
+ <<"lib/benchee/scenario_loader.ex">>,<<"lib/benchee/statistics.ex">>,
|
44
|
+ <<"lib/benchee/collection_data.ex">>,
|
45
|
+ <<"lib/benchee/relative_statistics.ex">>,<<"lib/benchee/benchmark.ex">>,
|
46
|
+ <<"lib/benchee/output">>,<<"lib/benchee/output/profile_printer.ex">>,
|
47
|
+ <<"lib/benchee/output/benchmark_printer.ex">>,<<"lib/benchee/formatters">>,
|
48
|
+ <<"lib/benchee/formatters/console">>,
|
49
|
+ <<"lib/benchee/formatters/console/run_time.ex">>,
|
50
|
+ <<"lib/benchee/formatters/console/helpers.ex">>,
|
51
|
+ <<"lib/benchee/formatters/console/memory.ex">>,
|
52
|
+ <<"lib/benchee/formatters/console/reductions.ex">>,
|
53
|
+ <<"lib/benchee/formatters/console.ex">>,
|
54
|
+ <<"lib/benchee/formatters/tagged_save.ex">>,<<"lib/benchee/benchmark">>,
|
55
|
+ <<"lib/benchee/benchmark/runner.ex">>,
|
56
|
+ <<"lib/benchee/benchmark/scenario_context.ex">>,
|
57
|
+ <<"lib/benchee/benchmark/run_once.ex">>,
|
58
|
+ <<"lib/benchee/benchmark/collect.ex">>,
|
59
|
+ <<"lib/benchee/benchmark/repeated_measurement.ex">>,
|
60
|
+ <<"lib/benchee/benchmark/function_call_overhead.ex">>,
|
61
|
+ <<"lib/benchee/benchmark/collect">>,
|
62
|
+ <<"lib/benchee/benchmark/collect/memory.ex">>,
|
63
|
+ <<"lib/benchee/benchmark/collect/profile.ex">>,
|
64
|
+ <<"lib/benchee/benchmark/collect/reductions.ex">>,
|
65
|
+ <<"lib/benchee/benchmark/collect/time.ex">>,
|
66
|
+ <<"lib/benchee/benchmark/hooks.ex">>,<<"lib/benchee.ex">>,
|
67
|
+ <<".formatter.exs">>,<<"mix.exs">>,<<"README.md">>,<<"LICENSE.md">>,
|
68
|
+ <<"CHANGELOG.md">>]}.
|
69
|
+ {<<"build_tools">>,[<<"mix">>]}.
|
changed
lib/benchee.ex
|
@@ -39,7 +39,7 @@ for {module, moduledoc} <- [{Benchee, elixir_doc}, {:benchee, erlang_doc}] do
|
39
39
|
time: 3
|
40
40
|
)
|
41
41
|
"""
|
42
|
- @spec run(map, keyword) :: any
|
42
|
+ @spec run(map, keyword) :: Benchee.Suite.t()
|
43
43
|
def run(jobs, config \\ []) when is_list(config) do
|
44
44
|
config
|
45
45
|
|> Benchee.init()
|
changed
lib/benchee/benchmark.ex
|
@@ -23,15 +23,34 @@ defmodule Benchee.Benchmark do
|
23
23
|
If there are inputs in the suite's config, a scenario will be added for the given
|
24
24
|
function for each input.
|
25
25
|
"""
|
26
|
- @spec benchmark(Suite.t(), Suite.key(), Scenario.benchmarking_function(), module) :: Suite.t()
|
27
|
- def benchmark(suite = %Suite{scenarios: scenarios}, job_name, function, printer \\ Printer) do
|
26
|
+ @spec benchmark(Suite.t(), Suite.key(), Scenario.to_benchmark(), module) :: Suite.t()
|
27
|
+ def benchmark(
|
28
|
+ suite = %Suite{scenarios: scenarios},
|
29
|
+ job_name,
|
30
|
+ to_be_benchmark,
|
31
|
+ printer \\ Printer
|
32
|
+ ) do
|
33
|
+ warn_if_evaluated(to_be_benchmark, job_name, printer)
|
34
|
+
|
28
35
|
normalized_name = to_string(job_name)
|
29
36
|
|
30
37
|
if duplicate?(scenarios, normalized_name) do
|
31
38
|
printer.duplicate_benchmark_warning(normalized_name)
|
32
39
|
suite
|
33
40
|
else
|
34
|
- add_scenario(suite, normalized_name, function)
|
41
|
+ add_scenario(suite, normalized_name, to_be_benchmark)
|
42
|
+ end
|
43
|
+ end
|
44
|
+
|
45
|
+ defp warn_if_evaluated(to_be_benchmark, job_name, printer) do
|
46
|
+ function =
|
47
|
+ case to_be_benchmark do
|
48
|
+ {function, _} -> function
|
49
|
+ function -> function
|
50
|
+ end
|
51
|
+
|
52
|
+ if :erlang.fun_info(function, :module) == {:module, :erl_eval} do
|
53
|
+ printer.evaluated_function_warning(job_name)
|
35
54
|
end
|
36
55
|
end
|
changed
lib/benchee/benchmark/collect.ex
|
@@ -12,7 +12,7 @@ defmodule Benchee.Benchmark.Collect do
|
12
12
|
reason - it will then be ignored and not counted.
|
13
13
|
"""
|
14
14
|
@type return_value :: {non_neg_integer | nil, any}
|
15
|
- @type zero_arity_function :: (() -> any)
|
15
|
+ @type zero_arity_function :: (-> any)
|
16
16
|
@type opts :: any
|
17
17
|
@callback collect(zero_arity_function()) :: return_value()
|
18
18
|
@callback collect(zero_arity_function(), opts) :: return_value()
|
changed
lib/benchee/benchmark/collect/memory.ex
|
@@ -27,7 +27,7 @@ defmodule Benchee.Benchmark.Collect.Memory do
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
- @spec collect((() -> any)) :: {nil | non_neg_integer, any}
|
30
|
+ @spec collect((-> any)) :: {nil | non_neg_integer, any}
|
31
31
|
def collect(fun) do
|
32
32
|
ref = make_ref()
|
33
33
|
Process.flag(:trap_exit, true)
|
changed
lib/benchee/benchmark/collect/time.ex
|
@@ -11,7 +11,7 @@ defmodule Benchee.Benchmark.Collect.Time do
|
11
11
|
|
12
12
|
@behaviour Benchee.Benchmark.Collect
|
13
13
|
|
14
|
- @spec collect((() -> any)) :: {non_neg_integer, any}
|
14
|
+ @spec collect((-> any)) :: {non_neg_integer, any}
|
15
15
|
def collect(function) do
|
16
16
|
start = :erlang.monotonic_time()
|
17
17
|
result = function.()
|
changed
lib/benchee/benchmark/function_call_overhead.ex
|
@@ -40,7 +40,7 @@ defmodule Benchee.Benchmark.FunctionCallOverhead do
|
40
40
|
do_run(function, [], end_time)
|
41
41
|
end
|
42
42
|
|
43
|
- @spec do_run((() -> any), [number], number) :: [number, ...]
|
43
|
+ @spec do_run((-> any), [number], number) :: [number, ...]
|
44
44
|
defp do_run(function, durations, end_time) do
|
45
45
|
{duration, _} = Time.collect(function)
|
changed
lib/benchee/benchmark/runner.ex
|
@@ -168,7 +168,7 @@ defmodule Benchee.Benchmark.Runner do
|
168
168
|
Enum.map(reductions, &(&1 - offset))
|
169
169
|
end
|
170
170
|
|
171
|
- defp run_reductions_benchmark(_, %ScenarioContext{config: %{reduction_time: 0.0}}) do
|
171
|
+ defp run_reductions_benchmark(_, %ScenarioContext{config: %{reduction_time: +0.0}}) do
|
172
172
|
[]
|
173
173
|
end
|
174
174
|
|
|
@@ -191,7 +191,7 @@ defmodule Benchee.Benchmark.Runner do
|
191
191
|
do_benchmark(scenario, new_context, Collect.Reductions, [])
|
192
192
|
end
|
193
193
|
|
194
|
- defp run_memory_benchmark(_, %ScenarioContext{config: %{memory_time: 0.0}}) do
|
194
|
+ defp run_memory_benchmark(_, %ScenarioContext{config: %{memory_time: +0.0}}) do
|
195
195
|
[]
|
196
196
|
end
|
197
197
|
|
|
@@ -216,7 +216,7 @@ defmodule Benchee.Benchmark.Runner do
|
216
216
|
|
217
217
|
@spec measure_runtimes(Scenario.t(), ScenarioContext.t(), number, boolean) :: [number]
|
218
218
|
defp measure_runtimes(scenario, context, run_time, fast_warning)
|
219
|
- defp measure_runtimes(_, _, 0.0, _), do: []
|
219
|
+ defp measure_runtimes(_, _, +0.0, _), do: []
|
220
220
|
|
221
221
|
defp measure_runtimes(scenario, scenario_context, run_time, fast_warning) do
|
222
222
|
end_time = current_time() + run_time
|
changed
lib/benchee/configuration.ex
|
@@ -176,7 +176,7 @@ defmodule Benchee.Configuration do
|
176
176
|
|
177
177
|
## Examples
|
178
178
|
|
179
|
- iex> Benchee.init
|
179
|
+ iex> init()
|
180
180
|
%Benchee.Suite{
|
181
181
|
configuration:
|
182
182
|
%Benchee.Configuration{
|
|
@@ -204,7 +204,7 @@ defmodule Benchee.Configuration do
|
204
204
|
scenarios: []
|
205
205
|
}
|
206
206
|
|
207
|
- iex> Benchee.init time: 1, warmup: 0.2
|
207
|
+ iex> init(time: 1, warmup: 0.2)
|
208
208
|
%Benchee.Suite{
|
209
209
|
configuration:
|
210
210
|
%Benchee.Configuration{
|
|
@@ -232,7 +232,7 @@ defmodule Benchee.Configuration do
|
232
232
|
scenarios: []
|
233
233
|
}
|
234
234
|
|
235
|
- iex> Benchee.init %{time: 1, warmup: 0.2}
|
235
|
+ iex> init(%{time: 1, warmup: 0.2})
|
236
236
|
%Benchee.Suite{
|
237
237
|
configuration:
|
238
238
|
%Benchee.Configuration{
|
|
@@ -260,7 +260,7 @@ defmodule Benchee.Configuration do
|
260
260
|
scenarios: []
|
261
261
|
}
|
262
262
|
|
263
|
- iex> Benchee.init(
|
263
|
+ iex> init(
|
264
264
|
...> parallel: 2,
|
265
265
|
...> time: 1,
|
266
266
|
...> warmup: 0.2,
|
changed
lib/benchee/conversion.ex
|
@@ -52,9 +52,9 @@ defmodule Benchee.Conversion do
|
52
52
|
}
|
53
53
|
"""
|
54
54
|
def units(scenarios, scaling_strategy) do
|
55
|
- run_time_measurements = measurments_for(scenarios, :run_time_data)
|
56
|
- reductions_measurements = measurments_for(scenarios, :reductions_data)
|
57
|
- memory_measurements = measurments_for(scenarios, :memory_usage_data)
|
55
|
+ run_time_measurements = measurements_for(scenarios, :run_time_data)
|
56
|
+ reductions_measurements = measurements_for(scenarios, :reductions_data)
|
57
|
+ memory_measurements = measurements_for(scenarios, :memory_usage_data)
|
58
58
|
|
59
59
|
%{
|
60
60
|
run_time: Duration.best(run_time_measurements.average, strategy: scaling_strategy),
|
|
@@ -64,7 +64,7 @@ defmodule Benchee.Conversion do
|
64
64
|
}
|
65
65
|
end
|
66
66
|
|
67
|
- defp measurments_for(scenarios, path) do
|
67
|
+ defp measurements_for(scenarios, path) do
|
68
68
|
paths = [Access.key(path), Access.key(:statistics)]
|
69
69
|
|
70
70
|
scenarios
|
changed
lib/benchee/conversion/count.ex
|
@@ -49,13 +49,13 @@ defmodule Benchee.Conversion.Count do
|
49
49
|
|
50
50
|
## Examples
|
51
51
|
|
52
|
- iex> {value, unit} = Benchee.Conversion.Count.scale(4_321.09)
|
52
|
+ iex> {value, unit} = scale(4_321.09)
|
53
53
|
iex> value
|
54
54
|
4.32109
|
55
55
|
iex> unit.name
|
56
56
|
:thousand
|
57
57
|
|
58
|
- iex> {value, unit} = Benchee.Conversion.Count.scale(0.0045)
|
58
|
+ iex> {value, unit} = scale(0.0045)
|
59
59
|
iex> value
|
60
60
|
0.0045
|
61
61
|
iex> unit.name
|
|
@@ -89,7 +89,7 @@ defmodule Benchee.Conversion.Count do
|
89
89
|
|
90
90
|
## Examples
|
91
91
|
|
92
|
- iex> Benchee.Conversion.Count.unit_for :thousand
|
92
|
+ iex> unit_for :thousand
|
93
93
|
%Benchee.Conversion.Unit{
|
94
94
|
name: :thousand,
|
95
95
|
magnitude: 1_000,
|
|
@@ -97,7 +97,7 @@ defmodule Benchee.Conversion.Count do
|
97
97
|
long: "Thousand"
|
98
98
|
}
|
99
99
|
|
100
|
- iex> Benchee.Conversion.Count.unit_for(%Benchee.Conversion.Unit{
|
100
|
+ iex> unit_for(%Benchee.Conversion.Unit{
|
101
101
|
...> name: :thousand,
|
102
102
|
...> magnitude: 1_000,
|
103
103
|
...> label: "K",
|
|
@@ -119,16 +119,16 @@ defmodule Benchee.Conversion.Count do
|
119
119
|
|
120
120
|
## Examples
|
121
121
|
|
122
|
- iex> Benchee.Conversion.Count.scale(12345, :one)
|
122
|
+ iex> scale(12345, :one)
|
123
123
|
12345.0
|
124
124
|
|
125
|
- iex> Benchee.Conversion.Count.scale(12345, :thousand)
|
125
|
+ iex> scale(12345, :thousand)
|
126
126
|
12.345
|
127
127
|
|
128
|
- iex> Benchee.Conversion.Count.scale(12345, :billion)
|
128
|
+ iex> scale(12345, :billion)
|
129
129
|
1.2345e-5
|
130
130
|
|
131
|
- iex> Benchee.Conversion.Count.scale(12345, :million)
|
131
|
+ iex> scale(12345, :million)
|
132
132
|
0.012345
|
133
133
|
|
134
134
|
"""
|
|
@@ -141,7 +141,7 @@ defmodule Benchee.Conversion.Count do
|
141
141
|
|
142
142
|
## Examples
|
143
143
|
|
144
|
- iex> {value, unit} = Benchee.Conversion.Count.convert({2500, :thousand}, :million)
|
144
|
+ iex> {value, unit} = convert({2500, :thousand}, :million)
|
145
145
|
iex> value
|
146
146
|
2.5
|
147
147
|
iex> unit.name
|
|
@@ -160,16 +160,16 @@ defmodule Benchee.Conversion.Count do
|
160
160
|
|
161
161
|
## Examples
|
162
162
|
|
163
|
- iex> Benchee.Conversion.Count.best([23, 23_000, 34_000, 2_340_000]).name
|
163
|
+ iex> best([23, 23_000, 34_000, 2_340_000]).name
|
164
164
|
:thousand
|
165
165
|
|
166
|
- iex> Benchee.Conversion.Count.best([23, 23_000, 34_000, 2_340_000, 3_450_000]).name
|
166
|
+ iex> best([23, 23_000, 34_000, 2_340_000, 3_450_000]).name
|
167
167
|
:million
|
168
168
|
|
169
|
- iex> Benchee.Conversion.Count.best([23, 23_000, 34_000, 2_340_000], strategy: :smallest).name
|
169
|
+ iex> best([23, 23_000, 34_000, 2_340_000], strategy: :smallest).name
|
170
170
|
:one
|
171
171
|
|
172
|
- iex> Benchee.Conversion.Count.best([23, 23_000, 34_000, 2_340_000], strategy: :largest).name
|
172
|
+ iex> best([23, 23_000, 34_000, 2_340_000], strategy: :largest).name
|
173
173
|
:million
|
174
174
|
|
175
175
|
"""
|
|
@@ -184,7 +184,7 @@ defmodule Benchee.Conversion.Count do
|
184
184
|
|
185
185
|
## Examples
|
186
186
|
|
187
|
- iex> Benchee.Conversion.Count.base_unit.name
|
187
|
+ iex> base_unit().name
|
188
188
|
:one
|
189
189
|
|
190
190
|
"""
|
|
@@ -196,16 +196,16 @@ defmodule Benchee.Conversion.Count do
|
196
196
|
|
197
197
|
## Examples
|
198
198
|
|
199
|
- iex> Benchee.Conversion.Count.format(45_678.9)
|
199
|
+ iex> format(45_678.9)
|
200
200
|
"45.68 K"
|
201
201
|
|
202
|
- iex> Benchee.Conversion.Count.format(45.6789)
|
202
|
+ iex> format(45.6789)
|
203
203
|
"45.68"
|
204
204
|
|
205
|
- iex> Benchee.Conversion.Count.format({45.6789, :thousand})
|
205
|
+ iex> format({45.6789, :thousand})
|
206
206
|
"45.68 K"
|
207
207
|
|
208
|
- iex> Benchee.Conversion.Count.format({45.6789, %Benchee.Conversion.Unit{long: "Thousand", magnitude: "1_000", label: "K"}})
|
208
|
+ iex> format({45.6789, %Benchee.Conversion.Unit{long: "Thousand", magnitude: "1_000", label: "K"}})
|
209
209
|
"45.68 K"
|
210
210
|
"""
|
211
211
|
def format(count) do
|
changed
lib/benchee/conversion/deviation_percent.ex
|
@@ -17,10 +17,10 @@ defmodule Benchee.Conversion.DeviationPercent do
|
17
17
|
|
18
18
|
## Examples
|
19
19
|
|
20
|
- iex> Benchee.Conversion.DeviationPercent.format(0.12345)
|
20
|
+ iex> format(0.12345)
|
21
21
|
"±12.35%"
|
22
22
|
|
23
|
- iex> Benchee.Conversion.DeviationPercent.format(1)
|
23
|
+ iex> format(1)
|
24
24
|
"±100.00%"
|
25
25
|
"""
|
26
26
|
def format(std_dev_ratio) do
|
changed
lib/benchee/conversion/duration.ex
|
@@ -65,19 +65,19 @@ defmodule Benchee.Conversion.Duration do
|
65
65
|
|
66
66
|
## Examples
|
67
67
|
|
68
|
- iex> {value, unit} = Benchee.Conversion.Duration.scale(1)
|
68
|
+ iex> {value, unit} = scale(1)
|
69
69
|
iex> value
|
70
70
|
1.0
|
71
71
|
iex> unit.name
|
72
72
|
:nanosecond
|
73
73
|
|
74
|
- iex> {value, unit} = Benchee.Conversion.Duration.scale(1_234)
|
74
|
+ iex> {value, unit} = scale(1_234)
|
75
75
|
iex> value
|
76
76
|
1.234
|
77
77
|
iex> unit.name
|
78
78
|
:microsecond
|
79
79
|
|
80
|
- iex> {value, unit} = Benchee.Conversion.Duration.scale(11_234_567_890_123)
|
80
|
+ iex> {value, unit} = scale(11_234_567_890_123)
|
81
81
|
iex> value
|
82
82
|
3.1207133028119443
|
83
83
|
iex> unit.name
|
|
@@ -118,7 +118,7 @@ defmodule Benchee.Conversion.Duration do
|
118
118
|
|
119
119
|
## Examples
|
120
120
|
|
121
|
- iex> Benchee.Conversion.Duration.unit_for :hour
|
121
|
+ iex> unit_for :hour
|
122
122
|
%Benchee.Conversion.Unit{
|
123
123
|
name: :hour,
|
124
124
|
magnitude: 3_600_000_000_000,
|
|
@@ -126,7 +126,7 @@ defmodule Benchee.Conversion.Duration do
|
126
126
|
long: "Hours"
|
127
127
|
}
|
128
128
|
|
129
|
- iex> Benchee.Conversion.Duration.unit_for(%Benchee.Conversion.Unit{
|
129
|
+ iex> unit_for(%Benchee.Conversion.Unit{
|
130
130
|
...> name: :hour,
|
131
131
|
...> magnitude: 3_600_000_000_000,
|
132
132
|
...> label: "h",
|
|
@@ -148,13 +148,13 @@ defmodule Benchee.Conversion.Duration do
|
148
148
|
|
149
149
|
## Examples
|
150
150
|
|
151
|
- iex> Benchee.Conversion.Duration.scale(12345, :nanosecond)
|
151
|
+ iex> scale(12345, :nanosecond)
|
152
152
|
12345.0
|
153
153
|
|
154
|
- iex> Benchee.Conversion.Duration.scale(12345, :microsecond)
|
154
|
+ iex> scale(12345, :microsecond)
|
155
155
|
12.345
|
156
156
|
|
157
|
- iex> Benchee.Conversion.Duration.scale(12345, :minute)
|
157
|
+ iex> scale(12345, :minute)
|
158
158
|
2.0575e-7
|
159
159
|
|
160
160
|
"""
|
|
@@ -167,7 +167,7 @@ defmodule Benchee.Conversion.Duration do
|
167
167
|
|
168
168
|
## Examples
|
169
169
|
|
170
|
- iex> {value, unit} = Benchee.Conversion.Duration.convert({90, :minute}, :hour)
|
170
|
+ iex> {value, unit} = convert({90, :minute}, :hour)
|
171
171
|
iex> value
|
172
172
|
1.5
|
173
173
|
iex> unit.name
|
|
@@ -182,14 +182,14 @@ defmodule Benchee.Conversion.Duration do
|
182
182
|
|
183
183
|
## Examples
|
184
184
|
|
185
|
- iex> Benchee.Conversion.Duration.convert_value({1.234, :second}, :microsecond)
|
185
|
+ iex> convert_value({1.234, :second}, :microsecond)
|
186
186
|
1_234_000.0
|
187
187
|
|
188
|
- iex> Benchee.Conversion.Duration.convert_value({1.234, :minute}, :microsecond)
|
188
|
+ iex> convert_value({1.234, :minute}, :microsecond)
|
189
189
|
7.404e7
|
190
190
|
|
191
|
- iex> microseconds = Benchee.Conversion.Duration.convert_value({1.234, :minute}, :microsecond)
|
192
|
- iex> {value, _} = Benchee.Conversion.Duration.convert({microseconds, :microsecond}, :minute)
|
191
|
+ iex> microseconds = convert_value({1.234, :minute}, :microsecond)
|
192
|
+ iex> {value, _} = convert({microseconds, :microsecond}, :minute)
|
193
193
|
iex> value
|
194
194
|
1.234
|
195
195
|
|
|
@@ -208,16 +208,16 @@ defmodule Benchee.Conversion.Duration do
|
208
208
|
|
209
209
|
## Examples
|
210
210
|
|
211
|
- iex> Benchee.Conversion.Duration.best([23, 23_000, 34_000, 2_340_000]).name
|
211
|
+ iex> best([23, 23_000, 34_000, 2_340_000]).name
|
212
212
|
:microsecond
|
213
213
|
|
214
|
- iex> Benchee.Conversion.Duration.best([23, 23_000, 34_000_000, 2_340_000_000, 3_450_000_000]).name
|
214
|
+ iex> best([23, 23_000, 34_000_000, 2_340_000_000, 3_450_000_000]).name
|
215
215
|
:second
|
216
216
|
|
217
|
- iex> Benchee.Conversion.Duration.best([23, 23_000, 34_000, 2_340_000], strategy: :smallest).name
|
217
|
+ iex> best([23, 23_000, 34_000, 2_340_000], strategy: :smallest).name
|
218
218
|
:nanosecond
|
219
219
|
|
220
|
- iex> Benchee.Conversion.Duration.best([23, 23_000, 34_000, 2_340_000_000], strategy: :largest).name
|
220
|
+ iex> best([23, 23_000, 34_000, 2_340_000_000], strategy: :largest).name
|
221
221
|
:second
|
222
222
|
"""
|
223
223
|
def best(list, opts \\ [strategy: :best])
|
|
@@ -231,7 +231,7 @@ defmodule Benchee.Conversion.Duration do
|
231
231
|
|
232
232
|
## Examples
|
233
233
|
|
234
|
- iex> Benchee.Conversion.Duration.base_unit.name
|
234
|
+ iex> base_unit().name
|
235
235
|
:nanosecond
|
236
236
|
|
237
237
|
"""
|
|
@@ -243,16 +243,16 @@ defmodule Benchee.Conversion.Duration do
|
243
243
|
|
244
244
|
## Examples
|
245
245
|
|
246
|
- iex> Benchee.Conversion.Duration.format(45_678.9)
|
246
|
+ iex> format(45_678.9)
|
247
247
|
"45.68 μs"
|
248
248
|
|
249
|
- iex> Benchee.Conversion.Duration.format(45.6789)
|
249
|
+ iex> format(45.6789)
|
250
250
|
"45.68 ns"
|
251
251
|
|
252
|
- iex> Benchee.Conversion.Duration.format({45.6789, :millisecond})
|
252
|
+ iex> format({45.6789, :millisecond})
|
253
253
|
"45.68 ms"
|
254
254
|
|
255
|
- iex> Benchee.Conversion.Duration.format {45.6789,
|
255
|
+ iex> format {45.6789,
|
256
256
|
...> %Benchee.Conversion.Unit{
|
257
257
|
...> long: "Milliseconds", magnitude: 1000, label: "ms"}
|
258
258
|
...> }
|
changed
lib/benchee/conversion/format.ex
|
@@ -41,7 +41,7 @@ defmodule Benchee.Conversion.Format do
|
41
41
|
formatted output. If no `separator/0` function exists, the default separator
|
42
42
|
(a single space) will be used.
|
43
43
|
|
44
|
- iex> Benchee.Conversion.Format.format({1.0, :kilobyte}, Benchee.Conversion.Memory)
|
44
|
+ iex> format({1.0, :kilobyte}, Benchee.Conversion.Memory)
|
45
45
|
"1 KB"
|
46
46
|
|
47
47
|
"""
|
changed
lib/benchee/conversion/memory.ex
|
@@ -56,14 +56,14 @@ defmodule Benchee.Conversion.Memory do
|
56
56
|
|
57
57
|
## Examples
|
58
58
|
|
59
|
- iex> {value, unit} = Benchee.Conversion.Memory.convert({1024, :kilobyte}, :megabyte)
|
59
|
+ iex> {value, unit} = convert({1024, :kilobyte}, :megabyte)
|
60
60
|
iex> value
|
61
61
|
1.0
|
62
62
|
iex> unit.name
|
63
63
|
:megabyte
|
64
64
|
|
65
|
- iex> current_unit = Benchee.Conversion.Memory.unit_for :kilobyte
|
66
|
- iex> {value, unit} = Benchee.Conversion.Memory.convert({1024, current_unit}, :megabyte)
|
65
|
+ iex> current_unit = unit_for :kilobyte
|
66
|
+ iex> {value, unit} = convert({1024, current_unit}, :megabyte)
|
67
67
|
iex> value
|
68
68
|
1.0
|
69
69
|
iex> unit.name
|
|
@@ -81,25 +81,25 @@ defmodule Benchee.Conversion.Memory do
|
81
81
|
|
82
82
|
## Examples
|
83
83
|
|
84
|
- iex> {value, unit} = Benchee.Conversion.Memory.scale(1)
|
84
|
+ iex> {value, unit} = scale(1)
|
85
85
|
iex> value
|
86
86
|
1.0
|
87
87
|
iex> unit.name
|
88
88
|
:byte
|
89
89
|
|
90
|
- iex> {value, unit} = Benchee.Conversion.Memory.scale(1_234)
|
90
|
+ iex> {value, unit} = scale(1_234)
|
91
91
|
iex> value
|
92
92
|
1.205078125
|
93
93
|
iex> unit.name
|
94
94
|
:kilobyte
|
95
95
|
|
96
|
- iex> {value, unit} = Benchee.Conversion.Memory.scale(11_234_567_890.123)
|
96
|
+ iex> {value, unit} = scale(11_234_567_890.123)
|
97
97
|
iex> value
|
98
98
|
10.463006692121736
|
99
99
|
iex> unit.name
|
100
100
|
:gigabyte
|
101
101
|
|
102
|
- iex> {value, unit} = Benchee.Conversion.Memory.scale(1_111_234_567_890.123)
|
102
|
+ iex> {value, unit} = scale(1_111_234_567_890.123)
|
103
103
|
iex> value
|
104
104
|
1.0106619519229962
|
105
105
|
iex> unit.name
|
|
@@ -140,7 +140,7 @@ defmodule Benchee.Conversion.Memory do
|
140
140
|
|
141
141
|
## Examples
|
142
142
|
|
143
|
- iex> Benchee.Conversion.Memory.unit_for :gigabyte
|
143
|
+ iex> unit_for :gigabyte
|
144
144
|
%Benchee.Conversion.Unit{
|
145
145
|
name: :gigabyte,
|
146
146
|
magnitude: 1_073_741_824,
|
|
@@ -148,7 +148,7 @@ defmodule Benchee.Conversion.Memory do
|
148
148
|
long: "Gigabytes"
|
149
149
|
}
|
150
150
|
|
151
|
- iex> Benchee.Conversion.Memory.unit_for(%Benchee.Conversion.Unit{
|
151
|
+ iex> unit_for(%Benchee.Conversion.Unit{
|
152
152
|
...> name: :gigabyte,
|
153
153
|
...> magnitude: 1_073_741_824,
|
154
154
|
...> label: "GB",
|
|
@@ -170,13 +170,13 @@ defmodule Benchee.Conversion.Memory do
|
170
170
|
|
171
171
|
## Examples
|
172
172
|
|
173
|
- iex> Benchee.Conversion.Memory.scale(12345, :kilobyte)
|
173
|
+ iex> scale(12345, :kilobyte)
|
174
174
|
12.0556640625
|
175
175
|
|
176
|
- iex> Benchee.Conversion.Memory.scale(12345, :megabyte)
|
176
|
+ iex> scale(12345, :megabyte)
|
177
177
|
0.011773109436035156
|
178
178
|
|
179
|
- iex> Benchee.Conversion.Memory.scale(123_456_789, :gigabyte)
|
179
|
+ iex> scale(123_456_789, :gigabyte)
|
180
180
|
0.11497809458523989
|
181
181
|
|
182
182
|
"""
|
|
@@ -195,16 +195,16 @@ defmodule Benchee.Conversion.Memory do
|
195
195
|
|
196
196
|
## Examples
|
197
197
|
|
198
|
- iex> Benchee.Conversion.Memory.best([23, 23_000, 34_000, 2_340_000]).name
|
198
|
+ iex> best([23, 23_000, 34_000, 2_340_000]).name
|
199
199
|
:kilobyte
|
200
200
|
|
201
|
- iex> Benchee.Conversion.Memory.best([23, 23_000, 34_000, 2_340_000, 3_450_000]).name
|
201
|
+ iex> best([23, 23_000, 34_000, 2_340_000, 3_450_000]).name
|
202
202
|
:megabyte
|
203
203
|
|
204
|
- iex> Benchee.Conversion.Memory.best([23, 23_000, 34_000, 2_340_000], strategy: :smallest).name
|
204
|
+ iex> best([23, 23_000, 34_000, 2_340_000], strategy: :smallest).name
|
205
205
|
:byte
|
206
206
|
|
207
|
- iex> Benchee.Conversion.Memory.best([23, 23_000, 34_000, 2_340_000], strategy: :largest).name
|
207
|
+ iex> best([23, 23_000, 34_000, 2_340_000], strategy: :largest).name
|
208
208
|
:megabyte
|
209
209
|
"""
|
210
210
|
def best(list, opts \\ [strategy: :best])
|
|
@@ -218,7 +218,7 @@ defmodule Benchee.Conversion.Memory do
|
218
218
|
|
219
219
|
## Examples
|
220
220
|
|
221
|
- iex> Benchee.Conversion.Memory.base_unit.name
|
221
|
+ iex> base_unit().name
|
222
222
|
:byte
|
223
223
|
|
224
224
|
"""
|
|
@@ -230,16 +230,16 @@ defmodule Benchee.Conversion.Memory do
|
230
230
|
|
231
231
|
## Examples
|
232
232
|
|
233
|
- iex> Benchee.Conversion.Memory.format(45_678.9)
|
233
|
+ iex> format(45_678.9)
|
234
234
|
"44.61 KB"
|
235
235
|
|
236
|
- iex> Benchee.Conversion.Memory.format(45.6789)
|
236
|
+ iex> format(45.6789)
|
237
237
|
"45.68 B"
|
238
238
|
|
239
|
- iex> Benchee.Conversion.Memory.format({45.6789, :kilobyte})
|
239
|
+ iex> format({45.6789, :kilobyte})
|
240
240
|
"45.68 KB"
|
241
241
|
|
242
|
- iex> Benchee.Conversion.Memory.format {45.6789,
|
242
|
+ iex> format {45.6789,
|
243
243
|
...> %Benchee.Conversion.Unit{
|
244
244
|
...> long: "Kilobytes", magnitude: 1024, label: "KB"}
|
245
245
|
...> }
|
changed
lib/benchee/conversion/scale.ex
|
@@ -61,7 +61,7 @@ defmodule Benchee.Conversion.Scale do
|
61
61
|
|
62
62
|
## Examples
|
63
63
|
|
64
|
- iex> Benchee.Conversion.Scale.scale(12345, :thousand, Benchee.Conversion.Count)
|
64
|
+ iex> scale(12345, :thousand, Benchee.Conversion.Count)
|
65
65
|
12.345
|
66
66
|
"""
|
67
67
|
def scale(value, unit = %Unit{}, _module) do
|
|
@@ -78,7 +78,7 @@ defmodule Benchee.Conversion.Scale do
|
78
78
|
## Examples
|
79
79
|
|
80
80
|
iex> unit = %Benchee.Conversion.Unit{magnitude: 1000}
|
81
|
- iex> Benchee.Conversion.Scale.scale 12345, unit
|
81
|
+ iex> scale 12345, unit
|
82
82
|
12.345
|
83
83
|
"""
|
84
84
|
def scale(value, %Unit{magnitude: magnitude}) do
|
|
@@ -130,31 +130,31 @@ defmodule Benchee.Conversion.Scale do
|
130
130
|
## Examples
|
131
131
|
|
132
132
|
iex> list = [1, 101, 1_001, 10_001, 100_001, 1_000_001]
|
133
|
- iex> Benchee.Conversion.Scale.best_unit(list, Benchee.Conversion.Count, strategy: :best).name
|
133
|
+ iex> best_unit(list, Benchee.Conversion.Count, strategy: :best).name
|
134
134
|
:thousand
|
135
135
|
|
136
136
|
iex> list = [1, 101, 1_001, 10_001, 100_001, 1_000_001]
|
137
|
- iex> Benchee.Conversion.Scale.best_unit(list, Benchee.Conversion.Count, strategy: :smallest).name
|
137
|
+ iex> best_unit(list, Benchee.Conversion.Count, strategy: :smallest).name
|
138
138
|
:one
|
139
139
|
|
140
140
|
iex> list = [1, 101, 1_001, 10_001, 100_001, 1_000_001]
|
141
|
- iex> Benchee.Conversion.Scale.best_unit(list, Benchee.Conversion.Count, strategy: :largest).name
|
141
|
+ iex> best_unit(list, Benchee.Conversion.Count, strategy: :largest).name
|
142
142
|
:million
|
143
143
|
|
144
144
|
iex> list = []
|
145
|
- iex> Benchee.Conversion.Scale.best_unit(list, Benchee.Conversion.Count, strategy: :best).name
|
145
|
+ iex> best_unit(list, Benchee.Conversion.Count, strategy: :best).name
|
146
146
|
:one
|
147
147
|
|
148
148
|
iex> list = [nil]
|
149
|
- iex> Benchee.Conversion.Scale.best_unit(list, Benchee.Conversion.Count, strategy: :best).name
|
149
|
+ iex> best_unit(list, Benchee.Conversion.Count, strategy: :best).name
|
150
150
|
:one
|
151
151
|
|
152
152
|
iex> list = [nil, nil, nil, nil]
|
153
|
- iex> Benchee.Conversion.Scale.best_unit(list, Benchee.Conversion.Count, strategy: :best).name
|
153
|
+ iex> best_unit(list, Benchee.Conversion.Count, strategy: :best).name
|
154
154
|
:one
|
155
155
|
|
156
156
|
iex> list = [nil, nil, nil, nil, 2_000]
|
157
|
- iex> Benchee.Conversion.Scale.best_unit(list, Benchee.Conversion.Count, strategy: :best).name
|
157
|
+ iex> best_unit(list, Benchee.Conversion.Count, strategy: :best).name
|
158
158
|
:thousand
|
159
159
|
"""
|
160
160
|
def best_unit(measurements, module, options) do
|
changed
lib/benchee/formatters/console.ex
|
@@ -80,7 +80,7 @@ defmodule Benchee.Formatters.Console do
|
80
80
|
...> unit_scaling: :best,
|
81
81
|
...> }
|
82
82
|
...> }
|
83
|
- iex> Benchee.Formatters.Console.format(suite, %{comparison: false, extended_statistics: false})
|
83
|
+ iex> format(suite, %{comparison: false, extended_statistics: false})
|
84
84
|
[["\n##### With input My input #####", "\nName ips average deviation median 99th %\n",
|
85
85
|
"My Job 5 K 200 ns ±10.00% 190 ns 300.10 ns\n",
|
86
86
|
"Job 2 2.50 K 400 ns ±20.00% 390 ns 500.10 ns\n"]]
|
changed
lib/benchee/formatters/console/run_time.ex
|
@@ -58,7 +58,7 @@ defmodule Benchee.Formatters.Console.RunTime do
|
58
58
|
...> }
|
59
59
|
...> ]
|
60
60
|
iex> configuration = %{comparison: false, unit_scaling: :best, extended_statistics: true}
|
61
|
- iex> Benchee.Formatters.Console.RunTime.format_scenarios(scenarios, configuration)
|
61
|
+ iex> format_scenarios(scenarios, configuration)
|
62
62
|
["\nName ips average deviation median 99th %\n",
|
63
63
|
"My Job 5 K 200 ns ±10.00% 190 ns 300.10 ns\n",
|
64
64
|
"Job 2 2.50 K 400 ns ±20.00% 390 ns 500.10 ns\n",
|
changed
lib/benchee/output/benchmark_printer.ex
|
@@ -3,6 +3,20 @@ defmodule Benchee.Output.BenchmarkPrinter do
|
3
3
|
|
4
4
|
alias Benchee.{Benchmark, Conversion.Duration}
|
5
5
|
|
6
|
+ @doc """
|
7
|
+ Shown when you try benchmark an evaluated function.
|
8
|
+
|
9
|
+ Compiled functions should be preferred as they are less likely to introduce additional overhead to your benchmark timing.
|
10
|
+ """
|
11
|
+ def evaluated_function_warning(job_name) do
|
12
|
+ IO.puts("""
|
13
|
+ Warning: the benchmark #{job_name} is using an evaluated function.
|
14
|
+ Evaluated functions perform slower than compiled functions.
|
15
|
+ You can move the Benchee caller to a function in a module and invoke `Mod.fun()` instead.
|
16
|
+ Alternatively, you can move the benchmark into a benchmark.exs file and run mix run benchmark.exs
|
17
|
+ """)
|
18
|
+ end
|
19
|
+
|
6
20
|
@doc """
|
7
21
|
Shown when you try to define a benchmark with the same name twice.
|
8
22
|
|
|
@@ -80,7 +94,7 @@ defmodule Benchee.Output.BenchmarkPrinter do
|
80
94
|
"""
|
81
95
|
def benchmarking(_, _, %{print: %{benchmarking: false}}), do: nil
|
82
96
|
|
83
|
- def benchmarking(_, _, %{time: 0.0, warmup: 0.0, memory_time: 0.0, reduction_time: 0.0}),
|
97
|
+ def benchmarking(_, _, %{time: +0.0, warmup: +0.0, memory_time: +0.0, reduction_time: +0.0}),
|
84
98
|
do: nil
|
85
99
|
|
86
100
|
def benchmarking(name, input_name, _config) do
|
changed
lib/benchee/relative_statistics.ex
|
@@ -95,8 +95,8 @@ defmodule Benchee.RelativeStatistics do
|
95
95
|
}
|
96
96
|
end
|
97
97
|
|
98
|
- defp zero_safe_division(0.0, 0.0), do: 1.0
|
98
|
+ defp zero_safe_division(+0.0, +0.0), do: 1.0
|
99
99
|
defp zero_safe_division(_, 0), do: :infinity
|
100
|
- defp zero_safe_division(_, 0.0), do: :infinity
|
100
|
+ defp zero_safe_division(_, +0.0), do: :infinity
|
101
101
|
defp zero_safe_division(a, b), do: a / b
|
102
102
|
end
|
changed
lib/benchee/scenario.ex
|
@@ -40,7 +40,14 @@ defmodule Benchee.Scenario do
|
40
40
|
|
41
41
|
No arguments if no inputs are used, one argument if inputs are used.
|
42
42
|
"""
|
43
|
- @type benchmarking_function :: (() -> any) | (any -> any)
|
43
|
+ @type benchmarking_function :: (-> any) | (any -> any)
|
44
|
+
|
45
|
+ @typedoc """
|
46
|
+ What shall be benchmarked, mostly a function but can contain options.
|
47
|
+
|
48
|
+ Options are there for hooks (`after_each`, `before_each` etc.)
|
49
|
+ """
|
50
|
+ @type to_benchmark :: benchmarking_function() | {benchmarking_function(), keyword()}
|
44
51
|
|
45
52
|
@typedoc """
|
46
53
|
All the data collected for a scenario (combination of function and input)
|
|
@@ -73,12 +80,13 @@ defmodule Benchee.Scenario do
|
73
80
|
|
74
81
|
## Examples
|
75
82
|
|
76
|
- iex> alias Benchee.Scenario
|
77
|
- iex> Scenario.display_name(%Scenario{job_name: "flat_map"})
|
83
|
+ iex> display_name(%Benchee.Scenario{job_name: "flat_map"})
|
78
84
|
"flat_map"
|
79
|
- iex> Scenario.display_name(%Scenario{job_name: "flat_map", tag: "main"})
|
85
|
+
|
86
|
+ iex> display_name(%Benchee.Scenario{job_name: "flat_map", tag: "main"})
|
80
87
|
"flat_map (main)"
|
81
|
- iex> Scenario.display_name(%{job_name: "flat_map"})
|
88
|
+
|
89
|
+ iex> display_name(%{job_name: "flat_map"})
|
82
90
|
"flat_map"
|
83
91
|
"""
|
84
92
|
@spec display_name(t) :: String.t()
|
|
@@ -86,6 +94,53 @@ defmodule Benchee.Scenario do
|
86
94
|
def display_name(%{job_name: job_name, tag: tag}), do: "#{job_name} (#{tag})"
|
87
95
|
def display_name(%{job_name: job_name}), do: job_name
|
88
96
|
|
97
|
+ @doc """
|
98
|
+ Returns the different measurement types supported.
|
99
|
+
|
100
|
+
|
101
|
+ ## Examples
|
102
|
+
|
103
|
+ iex> measurement_types()
|
104
|
+ [:run_time, :memory, :reductions]
|
105
|
+ """
|
106
|
+ @spec measurement_types :: [:memory | :reductions | :run_time, ...]
|
107
|
+ def measurement_types, do: [:run_time, :memory, :reductions]
|
108
|
+
|
109
|
+ @doc """
|
110
|
+ Given the measurement type name given by `measurement_types/0`, get the associated data.
|
111
|
+
|
112
|
+ Raises if no correct measurement type was specified.
|
113
|
+
|
114
|
+ ## Examples
|
115
|
+
|
116
|
+ iex> scenario = %Benchee.Scenario{run_time_data: %Benchee.CollectionData{statistics: %Benchee.Statistics{sample_size: 1}}}
|
117
|
+ iex> measurement_data(scenario, :run_time)
|
118
|
+ %Benchee.CollectionData{statistics: %Benchee.Statistics{sample_size: 1}}
|
119
|
+
|
120
|
+ iex> scenario = %Benchee.Scenario{memory_usage_data: %Benchee.CollectionData{statistics: %Benchee.Statistics{sample_size: 2}}}
|
121
|
+ iex> measurement_data(scenario, :memory)
|
122
|
+ %Benchee.CollectionData{statistics: %Benchee.Statistics{sample_size: 2}}
|
123
|
+
|
124
|
+ iex> scenario = %Benchee.Scenario{reductions_data: %Benchee.CollectionData{statistics: %Benchee.Statistics{sample_size: 3}}}
|
125
|
+ iex> measurement_data(scenario, :reductions)
|
126
|
+ %Benchee.CollectionData{statistics: %Benchee.Statistics{sample_size: 3}}
|
127
|
+
|
128
|
+ iex> measurement_data(%Benchee.Scenario{}, :memory)
|
129
|
+ %Benchee.CollectionData{}
|
130
|
+
|
131
|
+ iex> measurement_data(%Benchee.Scenario{}, :invalid)
|
132
|
+ ** (FunctionClauseError) no function clause matching in Benchee.Scenario.measurement_data/2
|
133
|
+ """
|
134
|
+ @spec measurement_data(t, :memory | :reductions | :run_time) :: CollectionData.t()
|
135
|
+ # Arguably this access is OO-ish/not great. However, with the incosistency we have in naming
|
136
|
+ # between the scenario struct fields and the measurement types this should be good/covnenient.
|
137
|
+ # Technically, we could/should move to a map structure from "measurement_type" to collection
|
138
|
+ # data but it's probably not worth breaking compatibility for right now.
|
139
|
+ def measurement_data(scenario, measurement_type)
|
140
|
+ def measurement_data(scenario, :run_time), do: scenario.run_time_data
|
141
|
+ def measurement_data(scenario, :memory), do: scenario.memory_usage_data
|
142
|
+ def measurement_data(scenario, :reductions), do: scenario.reductions_data
|
143
|
+
|
89
144
|
@doc """
|
90
145
|
Returns `true` if data of the provided type has been fully procsessed, `false` otherwise.
|
91
146
|
|
|
@@ -97,16 +152,20 @@ defmodule Benchee.Scenario do
|
97
152
|
|
98
153
|
## Examples
|
99
154
|
|
100
|
- iex> alias Benchee.Scenario
|
101
|
- iex> alias Benchee.Statistics
|
102
|
- iex> scenario = %Scenario{run_time_data: %Benchee.CollectionData{statistics: %Statistics{sample_size: 100}}}
|
103
|
- iex> Scenario.data_processed?(scenario, :run_time)
|
155
|
+ iex> scenario = %Benchee.Scenario{run_time_data: %Benchee.CollectionData{statistics: %Benchee.Statistics{sample_size: 100}}}
|
156
|
+ iex> data_processed?(scenario, :run_time)
|
104
157
|
true
|
105
|
- iex> scenario = %Scenario{memory_usage_data: %Benchee.CollectionData{statistics: %Statistics{sample_size: 1}}}
|
106
|
- iex> Scenario.data_processed?(scenario, :memory)
|
158
|
+
|
159
|
+ iex> scenario = %Benchee.Scenario{memory_usage_data: %Benchee.CollectionData{statistics: %Benchee.Statistics{sample_size: 1}}}
|
160
|
+ iex> data_processed?(scenario, :memory)
|
107
161
|
true
|
108
|
- iex> scenario = %Scenario{memory_usage_data: %Benchee.CollectionData{statistics: %Statistics{sample_size: 0}}}
|
109
|
- iex> Scenario.data_processed?(scenario, :memory)
|
162
|
+
|
163
|
+ iex> scenario = %Benchee.Scenario{reductions_data: %Benchee.CollectionData{statistics: %Benchee.Statistics{sample_size: 1}}}
|
164
|
+ iex> data_processed?(scenario, :reductions)
|
165
|
+ true
|
166
|
+
|
167
|
+ iex> scenario = %Benchee.Scenario{memory_usage_data: %Benchee.CollectionData{statistics: %Benchee.Statistics{sample_size: 0}}}
|
168
|
+ iex> data_processed?(scenario, :memory)
|
110
169
|
false
|
111
170
|
"""
|
112
171
|
@spec data_processed?(t, :run_time | :memory) :: boolean
|
|
@@ -117,4 +176,8 @@ defmodule Benchee.Scenario do
|
117
176
|
def data_processed?(scenario, :memory) do
|
118
177
|
scenario.memory_usage_data.statistics.sample_size > 0
|
119
178
|
end
|
179
|
+
|
180
|
+ def data_processed?(scenario, :reductions) do
|
181
|
+ scenario.reductions_data.statistics.sample_size > 0
|
182
|
+ end
|
120
183
|
end
|
changed
lib/benchee/statistics.ex
|
@@ -115,7 +115,7 @@ defmodule Benchee.Statistics do
|
115
115
|
...> }
|
116
116
|
...> ]
|
117
117
|
iex> suite = %Benchee.Suite{scenarios: scenarios}
|
118
|
- iex> Benchee.Statistics.statistics(suite)
|
118
|
+ iex> statistics(suite)
|
119
119
|
%Benchee.Suite{
|
120
120
|
scenarios: [
|
121
121
|
%Benchee.Scenario{
|
|
@@ -224,7 +224,7 @@ defmodule Benchee.Statistics do
|
224
224
|
end
|
225
225
|
|
226
226
|
defp add_ips(statistics = %__MODULE__{sample_size: 0}), do: statistics
|
227
|
- defp add_ips(statistics = %__MODULE__{average: 0.0}), do: statistics
|
227
|
+ defp add_ips(statistics = %__MODULE__{average: +0.0}), do: statistics
|
228
228
|
|
229
229
|
defp add_ips(statistics) do
|
230
230
|
ips = Duration.convert_value({1, :second}, :nanosecond) / statistics.average
|
changed
lib/benchee/suite.ex
|
@@ -47,3 +47,103 @@ defimpl DeepMerge.Resolver, for: Benchee.Suite do
|
47
47
|
Map.merge(original, override, resolver)
|
48
48
|
end
|
49
49
|
end
|
50
|
+
|
51
|
+ if Code.ensure_loaded?(Table.Reader) do
|
52
|
+ defimpl Table.Reader, for: Benchee.Suite do
|
53
|
+ alias Benchee.CollectionData
|
54
|
+ alias Benchee.Scenario
|
55
|
+
|
56
|
+ def init(suite) do
|
57
|
+ measurements_processed = map_measurements_processed(suite)
|
58
|
+ columns = get_columns_from_suite(suite, measurements_processed)
|
59
|
+ {rows, count} = extract_rows_from_suite(suite, measurements_processed)
|
60
|
+
|
61
|
+ {:rows, %{columns: columns, count: count}, rows}
|
62
|
+ end
|
63
|
+
|
64
|
+ defp map_measurements_processed(suite) do
|
65
|
+ Enum.filter(Scenario.measurement_types(), fn type ->
|
66
|
+ Enum.any?(suite.scenarios, fn scenario -> Scenario.data_processed?(scenario, type) end)
|
67
|
+ end)
|
68
|
+ end
|
69
|
+
|
70
|
+ @run_time_fields [
|
71
|
+ "samples",
|
72
|
+ "ips",
|
73
|
+ "average",
|
74
|
+ "std_dev",
|
75
|
+ "median",
|
76
|
+ "minimum",
|
77
|
+ "maximum",
|
78
|
+ "mode",
|
79
|
+ "sample_size"
|
80
|
+ ]
|
81
|
+
|
82
|
+ @non_run_time_fields List.delete(@run_time_fields, "ips")
|
83
|
+
|
84
|
+ defp get_columns_from_suite(suite, measurements_processed) do
|
85
|
+ config_percentiles = suite.configuration.percentiles
|
86
|
+
|
87
|
+ percentile_labels =
|
88
|
+ Enum.map(config_percentiles, fn percentile ->
|
89
|
+ "p_#{percentile}"
|
90
|
+ end)
|
91
|
+
|
92
|
+ measurement_headers =
|
93
|
+ Enum.flat_map(measurements_processed, fn measurement_type ->
|
94
|
+ fields = fields_for(measurement_type) ++ percentile_labels
|
95
|
+
|
96
|
+ Enum.map(fields, fn field -> "#{measurement_type}_#{field}" end)
|
97
|
+ end)
|
98
|
+
|
99
|
+ ["job_name" | measurement_headers]
|
100
|
+ end
|
101
|
+
|
102
|
+ defp fields_for(:run_time), do: @run_time_fields
|
103
|
+ defp fields_for(_), do: @non_run_time_fields
|
104
|
+
|
105
|
+ defp extract_rows_from_suite(suite, measurements_processed) do
|
106
|
+ config_percentiles = suite.configuration.percentiles
|
107
|
+
|
108
|
+ Enum.map_reduce(suite.scenarios, 0, fn %Scenario{} = scenario, count ->
|
109
|
+ secenario_data =
|
110
|
+ Enum.flat_map(measurements_processed, fn measurement_type ->
|
111
|
+ scenario
|
112
|
+ |> Scenario.measurement_data(measurement_type)
|
113
|
+ |> get_stats_from_collection_data(measurement_type, config_percentiles)
|
114
|
+ end)
|
115
|
+
|
116
|
+ row = [scenario.job_name | secenario_data]
|
117
|
+
|
118
|
+ {row, count + 1}
|
119
|
+ end)
|
120
|
+ end
|
121
|
+
|
122
|
+ defp get_stats_from_collection_data(
|
123
|
+ %CollectionData{statistics: statistics, samples: samples},
|
124
|
+ measurement_type,
|
125
|
+ percentiles
|
126
|
+ ) do
|
127
|
+ percentile_data =
|
128
|
+ Enum.map(percentiles, fn percentile -> statistics.percentiles[percentile] end)
|
129
|
+
|
130
|
+ Enum.concat([
|
131
|
+ [samples],
|
132
|
+ maybe_ips(statistics, measurement_type),
|
133
|
+ [
|
134
|
+ statistics.average,
|
135
|
+ statistics.std_dev,
|
136
|
+ statistics.median,
|
137
|
+ statistics.minimum,
|
138
|
+ statistics.maximum,
|
139
|
+ statistics.mode,
|
140
|
+ statistics.sample_size
|
141
|
+ ],
|
142
|
+ percentile_data
|
143
|
+ ])
|
144
|
+ end
|
145
|
+
|
146
|
+ defp maybe_ips(statistics, :run_time), do: [statistics.ips]
|
147
|
+ defp maybe_ips(_, _not_run_time), do: []
|
148
|
+ end
|
149
|
+ end
|
changed
lib/benchee/system.ex
|
@@ -37,8 +37,14 @@ defmodule Benchee.System do
|
37
37
|
{:ok, version} ->
|
38
38
|
String.trim(version)
|
39
39
|
|
40
|
+ # Livebook seemingly doesn't have the file where we expect it to be:
|
41
|
+ # https://github.com/bencheeorg/benchee/issues/367
|
40
42
|
{:error, reason} ->
|
41
|
- IO.puts("Error trying to determine erlang version #{reason}")
|
43
|
+ IO.puts(
|
44
|
+ "Error trying to determine erlang version #{reason}, falling back to overall OTP version"
|
45
|
+ )
|
46
|
+
|
47
|
+ to_string(otp_release)
|
42
48
|
end
|
43
49
|
end
|
44
50
|
|
|
@@ -179,11 +185,22 @@ defmodule Benchee.System do
|
179
185
|
end
|
180
186
|
end
|
181
187
|
|
182
|
- defp all_protocols_consolidated? do
|
183
|
- path = :code.lib_dir(:elixir, :ebin)
|
188
|
+ # just made public for easy testing purposes
|
189
|
+ @doc false
|
190
|
+ def all_protocols_consolidated?(lib_dir_fun \\ &:code.lib_dir/2) do
|
191
|
+ case lib_dir_fun.(:elixir, :ebin) do
|
192
|
+ # do we get a good old erlang charlist?
|
193
|
+ path when is_list(path) ->
|
194
|
+ [path]
|
195
|
+ |> Protocol.extract_protocols()
|
196
|
+ |> Enum.all?(&Protocol.consolidated?/1)
|
184
197
|
|
185
|
- [path]
|
186
|
- |> Protocol.extract_protocols()
|
187
|
- |> Enum.all?(&Protocol.consolidated?/1)
|
198
|
+ _error ->
|
199
|
+ IO.puts(
|
200
|
+ "Could not check if protocols are consolidated. Running as escript? Defaulting to they are consolidated."
|
201
|
+ )
|
202
|
+
|
203
|
+ true
|
204
|
+ end
|
188
205
|
end
|
189
206
|
end
|
changed
lib/benchee/utility/deep_convert.ex
|
@@ -6,25 +6,25 @@ defmodule Benchee.Utility.DeepConvert do
|
6
6
|
|
7
7
|
## Examples
|
8
8
|
|
9
|
- iex> Benchee.Utility.DeepConvert.to_map([a: 1, b: 2])
|
9
|
+ iex> to_map([a: 1, b: 2])
|
10
10
|
%{a: 1, b: 2}
|
11
11
|
|
12
|
- iex> Benchee.Utility.DeepConvert.to_map([a: [b: 2], c: [d: 3, e: 4, e: 5]])
|
12
|
+ iex> to_map([a: [b: 2], c: [d: 3, e: 4, e: 5]])
|
13
13
|
%{a: %{b: 2}, c: %{d: 3, e: 5}}
|
14
14
|
|
15
|
- iex> Benchee.Utility.DeepConvert.to_map([a: [b: 2], c: [1, 2, 3], d: []])
|
15
|
+ iex> to_map([a: [b: 2], c: [1, 2, 3], d: []])
|
16
16
|
%{a: %{b: 2}, c: [1, 2, 3], d: []}
|
17
17
|
|
18
|
- iex> Benchee.Utility.DeepConvert.to_map(%{a: %{b: 2}, c: %{d: 3, e: 5}})
|
18
|
+ iex> to_map(%{a: %{b: 2}, c: %{d: 3, e: 5}})
|
19
19
|
%{a: %{b: 2}, c: %{d: 3, e: 5}}
|
20
20
|
|
21
|
- iex> Benchee.Utility.DeepConvert.to_map([])
|
21
|
+ iex> to_map([])
|
22
22
|
%{}
|
23
23
|
|
24
|
- iex> Benchee.Utility.DeepConvert.to_map([a: [b: [f: 5]]], [:a])
|
24
|
+ iex> to_map([a: [b: [f: 5]]], [:a])
|
25
25
|
%{a: [b: [f: 5]]}
|
26
26
|
|
27
|
- iex> Benchee.Utility.DeepConvert.to_map([a: [b: [f: 5]], c: [d: 3]], [:b])
|
27
|
+ iex> to_map([a: [b: [f: 5]], c: [d: 3]], [:b])
|
28
28
|
%{a: %{b: [f: 5]}, c: %{d: 3}}
|
29
29
|
"""
|
30
30
|
def to_map(structure, exclusions \\ [])
|
changed
lib/benchee/utility/erlang_version.ex
|
@@ -8,7 +8,7 @@ defmodule Benchee.Utility.ErlangVersion do
|
8
8
|
|
9
9
|
Used to check if a bugfix has already landed.
|
10
10
|
|
11
|
- Applies some manual massaging, as erlang likes to report versios number not compatible with
|
11
|
+ Applies some manual massaging, as erlang likes to report versions number not compatible with
|
12
12
|
SemVer. If we can't parse the version, to minimize false positives, we assume it's newer.
|
13
13
|
|
14
14
|
Only the `version_to_check` is treated loosely. `version_to_check` must be SemVer compatible,
|
|
@@ -16,68 +16,76 @@ defmodule Benchee.Utility.ErlangVersion do
|
16
16
|
|
17
17
|
## Examples
|
18
18
|
|
19
|
- iex> Benchee.Utility.ErlangVersion.includes_fixes_from?("22.0.0", "22.0.0")
|
19
|
+ iex> includes_fixes_from?("22.0.0", "22.0.0")
|
20
20
|
true
|
21
21
|
|
22
|
- iex> Benchee.Utility.ErlangVersion.includes_fixes_from?("22.0.1", "22.0.0")
|
22
|
+ iex> includes_fixes_from?("22.0.1", "22.0.0")
|
23
23
|
true
|
24
24
|
|
25
|
- iex> Benchee.Utility.ErlangVersion.includes_fixes_from?("22.0.0", "22.0.1")
|
25
|
+ iex> includes_fixes_from?("22.0.0", "22.0.1")
|
26
26
|
false
|
27
27
|
|
28
|
- iex> Benchee.Utility.ErlangVersion.includes_fixes_from?("22.0.4", "22.0.5")
|
28
|
+ iex> includes_fixes_from?("22.0.4", "22.0.5")
|
29
29
|
false
|
30
30
|
|
31
|
- iex> Benchee.Utility.ErlangVersion.includes_fixes_from?("22.0.4", "22.0.4")
|
31
|
+ iex> includes_fixes_from?("22.0.4", "22.0.4")
|
32
32
|
true
|
33
33
|
|
34
|
- iex> Benchee.Utility.ErlangVersion.includes_fixes_from?("22.0.5", "22.0.4")
|
34
|
+ iex> includes_fixes_from?("22.0.5", "22.0.4")
|
35
35
|
true
|
36
36
|
|
37
|
- iex> Benchee.Utility.ErlangVersion.includes_fixes_from?("21.999.9999", "22.0.0")
|
37
|
+ iex> includes_fixes_from?("21.999.9999", "22.0.0")
|
38
38
|
false
|
39
39
|
|
40
|
- iex> Benchee.Utility.ErlangVersion.includes_fixes_from?("23.0.0", "22.0.0")
|
40
|
+ iex> includes_fixes_from?("23.0.0", "22.0.0")
|
41
41
|
true
|
42
42
|
|
43
43
|
# weird longer version numbers work
|
44
|
- iex> Benchee.Utility.ErlangVersion.includes_fixes_from?("22.0.0.0", "22.0.0")
|
44
|
+ iex> includes_fixes_from?("22.0.0.0", "22.0.0")
|
45
45
|
true
|
46
46
|
|
47
|
- iex> Benchee.Utility.ErlangVersion.includes_fixes_from?("22.0.0.14", "22.0.0")
|
47
|
+ iex> includes_fixes_from?("22.0.0.14", "22.0.0")
|
48
48
|
true
|
49
49
|
|
50
|
- iex> Benchee.Utility.ErlangVersion.includes_fixes_from?("23.3.5.14", "22.0.0")
|
50
|
+ iex> includes_fixes_from?("23.3.5.14", "22.0.0")
|
51
51
|
true
|
52
52
|
|
53
|
- iex> Benchee.Utility.ErlangVersion.includes_fixes_from?("21.3.5.14", "22.0.0")
|
53
|
+ iex> includes_fixes_from?("21.3.5.14", "22.0.0")
|
54
54
|
false
|
55
55
|
|
56
56
|
# weird shorter version numbers work
|
57
|
- iex> Benchee.Utility.ErlangVersion.includes_fixes_from?("22.0", "22.0.0")
|
57
|
+ iex> includes_fixes_from?("22.0", "22.0.0")
|
58
58
|
true
|
59
59
|
|
60
|
- iex> Benchee.Utility.ErlangVersion.includes_fixes_from?("22.0", "22.0.1")
|
60
|
+ iex> includes_fixes_from?("22.0", "22.0.1")
|
61
61
|
false
|
62
62
|
|
63
|
- iex> Benchee.Utility.ErlangVersion.includes_fixes_from?("22.1", "22.0.0")
|
63
|
+ iex> includes_fixes_from?("22.1", "22.0.0")
|
64
64
|
true
|
65
65
|
|
66
|
- iex> Benchee.Utility.ErlangVersion.includes_fixes_from?("21.3", "22.0.0")
|
66
|
+ iex> includes_fixes_from?("21.3", "22.0.0")
|
67
67
|
false
|
68
68
|
|
69
69
|
# rc version numbers work
|
70
|
- iex> Benchee.Utility.ErlangVersion.includes_fixes_from?("22.0-rc3", "22.0.0")
|
70
|
+ iex> includes_fixes_from?("22.0-rc3", "22.0.0")
|
71
71
|
false
|
72
|
- iex> Benchee.Utility.ErlangVersion.includes_fixes_from?("23.0-rc0", "22.0.0")
|
72
|
+ iex> includes_fixes_from?("23.0-rc0", "22.0.0")
|
73
|
+ true
|
74
|
+
|
75
|
+ # since we are falling back to general OTP versions now, test those as well
|
76
|
+ iex> includes_fixes_from?("21", "22.0.0")
|
77
|
+ false
|
78
|
+ iex> includes_fixes_from?("22", "22.0.0")
|
79
|
+ true
|
80
|
+ iex> includes_fixes_from?("23.0", "22.0.0")
|
73
81
|
true
|
74
82
|
|
75
83
|
# completely broken versions are assumed to be good to avoid false positives
|
76
84
|
# as this is not a main functionality but code to potentially work around an older erlang
|
77
85
|
# bug.
|
78
|
- iex> Benchee.Utility.ErlangVersion.includes_fixes_from?("super erlang", "22.0.0")
|
86
|
+ iex> includes_fixes_from?("super erlang", "22.0.0")
|
79
87
|
true
|
80
|
- iex> Benchee.Utility.ErlangVersion.includes_fixes_from?("", "22.0.0")
|
88
|
+ iex> includes_fixes_from?("", "22.0.0")
|
81
89
|
true
|
82
90
|
"""
|
83
91
|
def includes_fixes_from?(version_to_check, reference_version) do
|
|
@@ -104,6 +112,7 @@ defmodule Benchee.Utility.ErlangVersion do
|
104
112
|
case dot_count do
|
105
113
|
3 -> Regex.replace(@last_version_segment, erlang_version, "")
|
106
114
|
1 -> deal_with_major_minor(erlang_version)
|
115
|
+ 0 -> "#{erlang_version}.0.0"
|
107
116
|
_ -> erlang_version
|
108
117
|
end
|
changed
lib/benchee/utility/file_creation.ex
|
@@ -65,46 +65,46 @@ defmodule Benchee.Utility.FileCreation do
|
65
65
|
|
66
66
|
## Examples
|
67
67
|
|
68
|
- iex> Benchee.Utility.FileCreation.interleave("abc.csv", "hello")
|
68
|
+ iex> interleave("abc.csv", "hello")
|
69
69
|
"abc_hello.csv"
|
70
70
|
|
71
|
- iex> Benchee.Utility.FileCreation.interleave("abc.csv", "Big Input")
|
71
|
+ iex> interleave("abc.csv", "Big Input")
|
72
72
|
"abc_big_input.csv"
|
73
73
|
|
74
|
- iex> Benchee.Utility.FileCreation.interleave("abc.csv", "String.length/1")
|
74
|
+ iex> interleave("abc.csv", "String.length/1")
|
75
75
|
"abc_string_length_1.csv"
|
76
76
|
|
77
|
- iex> Benchee.Utility.FileCreation.interleave("bench/abc.csv", "Big Input")
|
77
|
+ iex> interleave("bench/abc.csv", "Big Input")
|
78
78
|
"bench/abc_big_input.csv"
|
79
79
|
|
80
|
- iex> Benchee.Utility.FileCreation.interleave("bench/abc.csv",
|
80
|
+ iex> interleave("bench/abc.csv",
|
81
81
|
...> ["Big Input"])
|
82
82
|
"bench/abc_big_input.csv"
|
83
83
|
|
84
|
- iex> Benchee.Utility.FileCreation.interleave("abc.csv", [])
|
84
|
+ iex> interleave("abc.csv", [])
|
85
85
|
"abc.csv"
|
86
86
|
|
87
|
- iex> Benchee.Utility.FileCreation.interleave("bench/abc.csv",
|
87
|
+ iex> interleave("bench/abc.csv",
|
88
88
|
...> ["Big Input", "Comparison"])
|
89
89
|
"bench/abc_big_input_comparison.csv"
|
90
90
|
|
91
|
- iex> Benchee.Utility.FileCreation.interleave("bench/A B C.csv",
|
91
|
+ iex> interleave("bench/A B C.csv",
|
92
92
|
...> ["Big Input", "Comparison"])
|
93
93
|
"bench/A B C_big_input_comparison.csv"
|
94
94
|
|
95
|
- iex> Benchee.Utility.FileCreation.interleave("bench/abc.csv",
|
95
|
+ iex> interleave("bench/abc.csv",
|
96
96
|
...> ["Big Input", "Comparison", "great Stuff"])
|
97
97
|
"bench/abc_big_input_comparison_great_stuff.csv"
|
98
98
|
|
99
|
- iex> marker = Benchee.Benchmark.no_input
|
100
|
- iex> Benchee.Utility.FileCreation.interleave("abc.csv", marker)
|
99
|
+ iex> marker = Benchee.Benchmark.no_input()
|
100
|
+ iex> interleave("abc.csv", marker)
|
101
101
|
"abc.csv"
|
102
|
- iex> Benchee.Utility.FileCreation.interleave("abc.csv", [marker])
|
102
|
+ iex> interleave("abc.csv", [marker])
|
103
103
|
"abc.csv"
|
104
|
- iex> Benchee.Utility.FileCreation.interleave("abc.csv",
|
104
|
+ iex> interleave("abc.csv",
|
105
105
|
...> [marker, "Comparison"])
|
106
106
|
"abc_comparison.csv"
|
107
|
- iex> Benchee.Utility.FileCreation.interleave("abc.csv",
|
107
|
+ iex> interleave("abc.csv",
|
108
108
|
...> ["Something cool", marker, "Comparison"])
|
109
109
|
"abc_something_cool_comparison.csv"
|
110
110
|
"""
|
changed
mix.exs
|
@@ -2,7 +2,7 @@ defmodule Benchee.Mixfile do
|
2
2
|
use Mix.Project
|
3
3
|
|
4
4
|
@source_url "https://github.com/bencheeorg/benchee"
|
5
|
- @version "1.1.0"
|
5
|
+ @version "1.2.0"
|
6
6
|
|
7
7
|
def project do
|
8
8
|
[
|
|
@@ -26,8 +26,9 @@ defmodule Benchee.Mixfile do
|
26
26
|
"safe_coveralls.travis": :test
|
27
27
|
],
|
28
28
|
dialyzer: [
|
29
|
- flags: [:unmatched_returns, :error_handling, :race_conditions, :underspecs],
|
30
|
- plt_file: {:no_warn, "tools/plts/benchee.plt"}
|
29
|
+ flags: [:unmatched_returns, :error_handling, :underspecs],
|
30
|
+ plt_file: {:no_warn, "tools/plts/benchee.plt"},
|
31
|
+ plt_add_apps: [:table]
|
31
32
|
],
|
32
33
|
name: "Benchee",
|
33
34
|
description: """
|
|
@@ -45,16 +46,23 @@ defmodule Benchee.Mixfile do
|
45
46
|
end
|
46
47
|
|
47
48
|
defp deps do
|
48
|
- [
|
49
|
+ deps = [
|
49
50
|
{:deep_merge, "~> 1.0"},
|
50
51
|
{:statistex, "~> 1.0"},
|
51
52
|
{:ex_guard, "~> 1.3", only: :dev},
|
52
53
|
{:credo, "~> 1.0", only: :dev, runtime: false},
|
53
54
|
{:ex_doc, ">= 0.0.0", only: :dev, runtime: false},
|
54
55
|
{:excoveralls, "~> 0.13", only: :test},
|
55
|
- {:inch_ex, "~> 2.0", only: :docs, runtime: false},
|
56
56
|
{:dialyxir, "~> 1.0", only: :dev, runtime: false}
|
57
57
|
]
|
58
|
+
|
59
|
+ # table relies on __STACKTRACE__ which was introduced in 1.7, we still support ~>1.6 though
|
60
|
+ # as it's optional, this does not affect the function of Benchee
|
61
|
+ if Version.compare(System.version(), "1.7.0") == :gt do
|
62
|
+ [{:table, "~> 0.1.0", optional: true} | deps]
|
63
|
+ else
|
64
|
+ deps
|
65
|
+ end
|
58
66
|
end
|
59
67
|
|
60
68
|
defp package do
|