Well your dot
function is using pattern matching while your match
function is using the .
operator which is confusing! Probably a mistake or we are maybe not talking about the same things.
I ran a slightly different benchmark and the results are non significant. thank you because I’ll use .
a lot more from now on as we took the time to test that.
Here is the benckmark
inputs = %{
"large" => Map.new(1..33, fn n -> {:"key_#{n}", []} end),
"single" => %{key_1: []}
}
Benchee.run(
%{
"body_match" => fn map ->
%{key_1: value} = map
value
end,
"case" => fn map ->
case map do
%{key_1: value} -> value
end
end,
"dot" => fn map ->
map.key_1
end,
"head_match" => fn
%{key_1: value} ->
value
end
},
inputs: inputs,
pre_check: true,
time: 1
)
Had to set time: 1
or otherwise my RAM is entirely taken after the last scenario/input runs. No matter which one. Also it does not max out my CPU.
So I ran this instead, which has more overhead but keeps your technique of looping inside the scenarios so there are less results to compute (I guess that is what makes benchee eat all the ram) but not building lists (as in for
expressions) to save RAM. But I get way more consistent results. The only thing I see is that matching in the function head is 1.20x slower except with large maps (more than 32 keys).
inputs =
defmodule Soda do
@counts 1..10_000
def inputs do
%{
"large" => Map.new(1..33, fn n -> {:"key_#{n}", 0} end),
"small" => Map.new(1..32, fn n -> {:"key_#{n}", 0} end),
"single" => %{key_15: 0}
}
end
def body_match(map) do
%{key_15: value} = map
value
end
def case_expr(map) do
case map do
%{key_15: value} -> value
end
end
def dot(map) do
map.key_15
end
def head_match(%{key_15: value}) do
value
end
def run do
Benchee.run(
%{
"body_match" => fn map -> Enum.reduce(@counts, 0, fn _, _ -> body_match(map) end) end,
"case_expr" => fn map -> Enum.reduce(@counts, 0, fn _, _ -> case_expr(map) end) end,
"dot" => fn map -> Enum.reduce(@counts, 0, fn _, _ -> dot(map) end) end,
"head_match" => fn map -> Enum.reduce(@counts, 0, fn _, _ -> head_match(map) end) end
},
inputs: inputs(),
pre_check: true,
time: 5
)
end
end
Soda.run()
So, this was fun but the conclusion is that there is no difference. Sorry for derailing the topic!