Why isn't template matching performance much better than ifelse / cond in elixir?

I was told that erlang beam is tuned a lot to match the pattern, so performance is much better than conditional expression. I ran a test in an elixir and ran a test using benchfella. However, I found that the pattern matching performance is almost equal to the performance level compared to 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 kernel code, which basically formats the data for a string in a different situation. The entire project can be obtained through 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 something? Or do I need more sophisticated tests to find out the power of erlang VM pattern matching?

+4
1

:

  • - , , , (O(N)), (O(log2N))

  • , . ,

, , , , Elixir Unicode:

case codepoint do
  ?á -> ?Á
  ?é -> ?É
  ?í -> ?Í
  ...
  ?ū -> ?Ū
end

VM , , .

Erlang VM, , . , , , .

+18

All Articles