Skip to content

Commit

Permalink
Merge pull request #10 from PragTob/update-benchee-version
Browse files Browse the repository at this point in the history
Update benchee version
  • Loading branch information
PragTob committed Aug 27, 2018
2 parents 8fd528d + c0f50a8 commit 7c719bb
Show file tree
Hide file tree
Showing 10 changed files with 356 additions and 254 deletions.
159 changes: 159 additions & 0 deletions .credo.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
# This file contains the configuration for Credo and you are probably reading
# this after creating it with `mix credo.gen.config`.
#
# If you find anything wrong or unclear in this file, please report an
# issue on GitHub: https://github.com/rrrene/credo/issues
#
%{
#
# You can have as many configs as you like in the `configs:` field.
configs: [
%{
#
# Run any exec using `mix credo -C <name>`. If no exec name is given
# "default" is used.
#
name: "default",
#
# These are the files included in the analysis:
files: %{
#
# You can give explicit globs or simply directories.
# In the latter case `**/*.{ex,exs}` will be used.
#
included: ["lib/", "src/", "test/", "web/", "apps/"],
excluded: [~r"/_build/", ~r"/deps/"]
},
#
# If you create your own checks, you must specify the source files for
# them here, so they can be loaded by Credo before running the analysis.
#
requires: [],
#
# If you want to enforce a style guide and need a more traditional linting
# experience, you can change `strict` to `true` below:
#
strict: true,
#
# If you want to use uncolored output by default, you can change `color`
# to `false` below:
#
color: true,
#
# You can customize the parameters of any check by adding a second element
# to the tuple.
#
# To disable a check put `false` as second element:
#
# {Credo.Check.Design.DuplicatedCode, false}
#
checks: [
#
## Consistency Checks
#
{Credo.Check.Consistency.ExceptionNames},
{Credo.Check.Consistency.LineEndings},
{Credo.Check.Consistency.ParameterPatternMatching},
{Credo.Check.Consistency.SpaceAroundOperators},
{Credo.Check.Consistency.SpaceInParentheses},
{Credo.Check.Consistency.TabsOrSpaces},

#
## Design Checks
#
# You can customize the priority of any check
# Priority values are: `low, normal, high, higher`
#
{Credo.Check.Design.AliasUsage, false},
# For some checks, you can also set other parameters
#
# If you don't want the `setup` and `test` macro calls in ExUnit tests
# or the `schema` macro in Ecto schemas to trigger DuplicatedCode, just
# set the `excluded_macros` parameter to `[:schema, :setup, :test]`.
#
{Credo.Check.Design.DuplicatedCode, excluded_macros: []},
# You can also customize the exit_status of each check.
# If you don't want TODO comments to cause `mix credo` to fail, just
# set this value to 0 (zero).
#
{Credo.Check.Design.TagTODO, exit_status: 2},
{Credo.Check.Design.TagFIXME},

#
## Readability Checks
#
{Credo.Check.Readability.FunctionNames},
{Credo.Check.Readability.LargeNumbers},
{Credo.Check.Readability.MaxLineLength, priority: :low, max_length: 98},
{Credo.Check.Readability.ModuleAttributeNames},
{Credo.Check.Readability.ModuleDoc},
{Credo.Check.Readability.ModuleNames},
{Credo.Check.Readability.ParenthesesOnZeroArityDefs},
{Credo.Check.Readability.ParenthesesInCondition},
{Credo.Check.Readability.PredicateFunctionNames},
{Credo.Check.Readability.PreferImplicitTry},
{Credo.Check.Readability.RedundantBlankLines},
{Credo.Check.Readability.StringSigils},
{Credo.Check.Readability.TrailingBlankLine},
{Credo.Check.Readability.TrailingWhiteSpace},
{Credo.Check.Readability.VariableNames},
{Credo.Check.Readability.Semicolons},
{Credo.Check.Readability.SpaceAfterCommas},

#
## Refactoring Opportunities
#
{Credo.Check.Refactor.DoubleBooleanNegation},
{Credo.Check.Refactor.CondStatements},
{Credo.Check.Refactor.CyclomaticComplexity},
{Credo.Check.Refactor.FunctionArity},
{Credo.Check.Refactor.LongQuoteBlocks},
{Credo.Check.Refactor.MatchInCondition},
{Credo.Check.Refactor.NegatedConditionsInUnless},
{Credo.Check.Refactor.NegatedConditionsWithElse},
{Credo.Check.Refactor.Nesting},
{Credo.Check.Refactor.PipeChainStart,
excluded_argument_types: [:atom, :binary, :fn, :keyword], excluded_functions: []},
{Credo.Check.Refactor.UnlessWithElse},

#
## Warnings
#
{Credo.Check.Warning.BoolOperationOnSameValues},
{Credo.Check.Warning.ExpensiveEmptyEnumCheck},
{Credo.Check.Warning.IExPry},
{Credo.Check.Warning.IoInspect},
{Credo.Check.Warning.LazyLogging},
{Credo.Check.Warning.OperationOnSameValues},
{Credo.Check.Warning.OperationWithConstantResult},
{Credo.Check.Warning.UnusedEnumOperation},
{Credo.Check.Warning.UnusedFileOperation},
{Credo.Check.Warning.UnusedKeywordOperation},
{Credo.Check.Warning.UnusedListOperation},
{Credo.Check.Warning.UnusedPathOperation},
{Credo.Check.Warning.UnusedRegexOperation},
{Credo.Check.Warning.UnusedStringOperation},
{Credo.Check.Warning.UnusedTupleOperation},
{Credo.Check.Warning.RaiseInsideRescue},

#
# Controversial and experimental checks (opt-in, just remove `, false`)
#
{Credo.Check.Refactor.ABCSize, false},
{Credo.Check.Refactor.AppendSingleItem, false},
{Credo.Check.Refactor.VariableRebinding, false},
{Credo.Check.Warning.MapGetUnsafePass, false},
{Credo.Check.Consistency.MultiAliasImportRequireUse, false},

#
# Deprecated checks (these will be deleted after a grace period)
#
{Credo.Check.Readability.Specs, false}

#
# Custom checks can be created using `mix credo.gen.check`.
#
]
}
]
}
8 changes: 8 additions & 0 deletions .formatter.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[
inputs: [
"lib/**/*.{ex,exs}",
"test/**/*.{ex,exs}",
"mix/**/*.{ex,exs}",
"./mix.exs"
]
]
2 changes: 2 additions & 0 deletions .tool-versions
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
elixir 1.7.1
erlang 21.0
27 changes: 18 additions & 9 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,25 +1,34 @@
language: elixir
elixir:
- 1.4.5
- 1.5.2
- 1.6.0
- 1.5.3
- 1.6.6
- 1.7.1
otp_release:
- 18.3
- 19.3
- 20.2
- 20.3
- 21.0

matrix:
exclude:
- elixir: 1.6.0
otp_release: 18.3
- elixir: 1.4.5
otp_release: 21.0
- elixir: 1.5.3
otp_release: 21.0
- elixir: 1.7.1
otp_release: 19.3

before_script:
- MIX_ENV=test mix compile --warnings-as-errors
- travis_wait mix dialyzer --plt
script:
# skip dialyzer for elixir 1.4 and erlang 18 as it produces weird errors, see #69
- if ! ([[ "$TRAVIS_ELIXIR_VERSION" == "1.4"* ]] && [[ "$TRAVIS_OTP_RELEASE" == "18"* ]]); then mix dialyzer --halt-exit-status; fi
- mix credo --strict
- if [[ "$TRAVIS_ELIXIR_VERSION" == "1.6"* ]]; then mix format --check-formatted; fi
- mix dialyzer --halt-exit-status
- mix coveralls.travis
# need that sweet memory for dialyzer
after_script:
- mix deps.get --only docs
- MIX_ENV=docs mix inch.report
sudo: required
dist: trusty
cache:
Expand Down
103 changes: 54 additions & 49 deletions lib/benchee/formatters/json.ex
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
# Jason support for benchee structs
require Protocol
Enum.each([Benchee.Statistics], fn benchee_module ->
Protocol.derive(Jason.Encoder, benchee_module)
end)

defmodule Benchee.Formatters.JSON do
use Benchee.Formatter
Protocol.derive(Jason.Encoder, Benchee.Statistics)

defmodule Benchee.Formatters.JSON do
@moduledoc """
Functionality for converting Benchee benchmarking results to JSON so that
they can be written to file or just generated for your usage.
Expand All @@ -22,15 +19,16 @@ defmodule Benchee.Formatters.JSON do
"map.flatten" => fn -> list |> Enum.map(map_fun) |> List.flatten end
},
formatters: [
&Benchee.Formatters.JSON.output/1,
&Benchee.Formatters.Console.output/1
{Benchee.Formatters.JSON, file: "my.json"},
Benchee.Formatters.Console
],
formatter_options: [json: [file: "my.json"]]
)
"""

alias Benchee.{Suite, Configuration, Benchmark.Scenario}
@behaviour Benchee.Formatter

alias Benchee.{Suite, Statistics, Benchmark.Scenario, Utility.FileCreation}

@doc """
Formats the output of benchee to a map from input names to their associated
Expand Down Expand Up @@ -59,43 +57,44 @@ defmodule Benchee.Formatters.JSON do
...> percentiles: %{99 => 900}
...> }
...> },
...> ],
...> configuration: %Benchee.Configuration{
...> formatter_options: %{json: %{file: "my_file.json"}}
...> }
...> ]
...> }
iex> Benchee.Formatters.JSON.format(suite)
{%{"Some Input" => "{\\"run_times\\":{\\"My Job\\":[200,400,400,400,500,500,700,900]},\\"sort_order\\":[\\"My Job\\"],\\"statistics\\":{\\"My Job\\":{\\"average\\":500.0,\\"ips\\":2.0e3,\\"maximum\\":900,\\"median\\":450.0,\\"minimum\\":200,\\"mode\\":400,\\"percentiles\\":{\\"99\\":900},\\"sample_size\\":8,\\"std_dev\\":200.0,\\"std_dev_ips\\":800.0,\\"std_dev_ratio\\":0.4}}}"}, "my_file.json"}
iex> Benchee.Formatters.JSON.format(suite, %{file: "my_file.json"})
%{"Some Input" => "{\\"run_times\\":{\\"My Job\\":[200,400,400,400,500,500,700,900]},\\"sort_order\\":[\\"My Job\\"],\\"statistics\\":{\\"My Job\\":{\\"average\\":500.0,\\"ips\\":2.0e3,\\"maximum\\":900,\\"median\\":450.0,\\"minimum\\":200,\\"mode\\":400,\\"percentiles\\":{\\"99\\":900},\\"sample_size\\":8,\\"std_dev\\":200.0,\\"std_dev_ips\\":800.0,\\"std_dev_ratio\\":0.4}}}"}
"""
@spec format(Suite.t) :: {%{Suite.key => String.t}, String.t}
def format(%Suite{scenarios: scenarios, configuration:
%Configuration{formatter_options: %{json: %{file: filename}}}}) do
data = scenarios
|> Enum.group_by(fn(scenario) -> scenario.input_name end)
|> Enum.map(fn({input, scenarios}) ->
{input, format_scenarios_for_input(scenarios)}
end)
|> Map.new
{data, filename}
@spec format(Suite.t(), map) :: %{Suite.key() => String.t()}
def format(%Suite{scenarios: scenarios}, %{file: _}) do
scenarios
|> Enum.group_by(fn scenario -> scenario.input_name end)
|> Enum.map(fn {input, scenarios} ->
{input, format_scenarios_for_input(scenarios)}
end)
|> Map.new()
end
def format(_) do
raise "You need to specify a file to write the JSON to in the configuration as formatter_options: [json: [file: \"my.json\"]]"

def format(_, _) do
raise """
You need to specify a file to write the JSON to in the configuration a
formatter option:
formatters: [{Benchee.Formatters.JSON, file: \"my.json\"]]"}]
"""
end

@doc """
Uses the return value of `Benchee.Formatters.JSON.format/1` to write it to the
JSON file defined in the initial configuration under
`formatter_options: %{json: %{file: "my.json"}}`
JSON file defined in the initial configuration.
"""
@spec write({%{Suite.key => String.t}, String.t}) :: :ok
def write({data, filename}) do
Benchee.Utility.FileCreation.each(data, filename)
@spec write(%{Suite.key() => String.t()}, map) :: :ok
def write(data, %{file: file}) do
FileCreation.each(data, file)
:ok
end

# Do not make me private, poor HTML formatter relies on me so I might
# deserve a @doc at some point
# Do not make me private, poor HTML formatter relies on me
@doc false
@spec format_scenarios_for_input([Scenario.t()]) :: String.t()
def format_scenarios_for_input(scenarios) do
%{}
|> add_statistics(scenarios)
Expand All @@ -105,35 +104,41 @@ defmodule Benchee.Formatters.JSON do
end

defp add_statistics(output, scenarios) do
statistics = scenarios
|> Enum.map(fn(scenario) ->
{scenario.name, scenario.run_time_statistics}
end)
|> Map.new
statistics =
scenarios
|> Enum.map(fn scenario ->
{scenario.name, scenario.run_time_statistics}
end)
|> Map.new()

Map.put(output, "statistics", statistics)
end

# Sort order as determined by `Benchee.Statistics.sort`
defp add_sort_order(output, scenarios) do
sort_order = scenarios
|> Benchee.Statistics.sort
|> Enum.map(fn(%Scenario{name: name}) -> name end)
sort_order =
scenarios
|> Statistics.sort()
|> Enum.map(fn %Scenario{name: name} -> name end)

Map.put(output, "sort_order", sort_order)
end

defp add_run_times(output, scenarios) do
run_times = scenarios
|> Enum.map(fn(scenario) ->
{scenario.name, scenario.run_times}
end)
|> Map.new
run_times =
scenarios
|> Enum.map(fn scenario ->
{scenario.name, scenario.run_times}
end)
|> Map.new()

Map.put(output, "run_times", run_times)
end

@doc """
Simple wrapper for encoding a map/benchee structure to JSON.
Simple wrapper for encoding a map/benchee struct to JSON.
Decouples it from the actual JSON library (currently Poison) used by
Decouples it from the actual JSON library (currently Jason) used by
benchee_json so that other plugins can rely on it just working with a general
Benchee suite structure.
"""
Expand Down
Loading

0 comments on commit 7c719bb

Please sign in to comment.