I was told that erlang beam tuned a lot with pattern matching, thus the performance is much better than conditional expression. I did a test in elixir, and run the benchmark testing with benchfella. However, I found the pattern matching performance is almost the same level of performance compared with if/cond.
$ mix bench -d 10
Settings:
duration: 10.0 s
mem stats: false
sys mem stats: false
[12:30:08] 1/3: PatternMatchBench.if else performance
[12:30:28] 2/3: PatternMatchBench.cond performance
[12:30:47] 3/3: PatternMatchBench.pattern match performance
Finished in 57.5 seconds
PatternMatchBench.if else performance: 10000 1723.24 µs/op
PatternMatchBench.cond performance: 10000 1723.36 µs/op
PatternMatchBench.pattern match performance: 10000 1726.95 µs/op
Below is the core code, it basically format the data to string under different situation. The whole project could be obtained via https://github.com/tyrchen/pattern_match.
defmodule Ifelse do
def process(data) do
if is_list(data) do
data
|> Enum.map(fn(entry) ->
if is_tuple(entry) do
{k,v} = entry
"#{k}: #{v}" |> transform
else
entry |> process
end
end)
|> Enum.join("\n")
else
if is_map(data) do
data
|> Enum.map(fn({k, v}) -> transform("#{k}: #{v}") end)
|> Enum.join("\n")
else
data |> transform
end
end
end
defp transform(str) do
" #{str}"
end
end
defmodule Cond do
def process(data) do
cond do
is_list(data) ->
data
|> Enum.map(fn(item) ->
cond do
is_tuple(item) ->
{k, v} = item
"#{k}: #{v}" |> transform
true ->
item |> process
end
end)
|> Enum.join("\n")
is_map(data) ->
data
|> Enum.map(fn({k, v}) -> "#{k}: #{v}" |> transform end)
|> Enum.join("\n")
true ->
" #{data}"
end
end
defp transform(str) do
" #{str}"
end
end
defmodule Pattern do
def process(data) when is_tuple(data) do
{k, v} = data
"#{k}: #{v}" |> process
end
def process(data) when is_list(data) or is_map(data) do
data
|> Enum.map(fn(entry) -> process(entry) end)
|> Enum.join("\n")
end
def process(data) do
" #{data}"
end
end
Did I miss anything? Or do I need more complicated tests to find out the strength of the pattern matching of erlang VM?
foo({bar, A = 0, Z}) -> Z; foo({bar, A, Z = 0}) -> A; foo({bar, A, Z}) when A > Z -> A; foo({bar, A, Z}) -> Z; ..., as this kind of setup allows the BEAM compiler to build out decision trees for which clause of the functionfooto invoke. - Soup d'CampbellsNis small). - Tyr