1
votes

I want to get the first 3 bytes in a list of bytes in Elixir in my function get_color(image), where image is a struct with hex defined as the list of bytes.

Now I know the pattern matching way of this would be something like:

def get_color(image) do
    [a,b,c | _] = image.hex
    [a,b,c]
end

My initial code was however:

def get_color(image) do
    {color, _rest_of_array} = image.hex |> Enum.split(3)
    color
end

I want to know if both approaches are just as efficient, or whether Enum.split does some other background work that may make it slower? Or perhaps it consumes more memory because it also has to create the other half of the list?

Benchee test for my code (based on answer):

Name                 ips        average  deviation         median         99th %
match           184.23 M        5.43 ns   ┬▒149.37%           0 ns          31 ns
enum.split      2.35 M          425.32 ns ┬▒15.78%            454 ns        614 ns

Comparison:
match           184.23 M
enum.split      2.35 M - 78.36x slower +419.89 ns
2
You can easily test that with elixirschool.com/en/lessons/libraries/benchee - Tano
Asking if both approaches are "just as efficient" is assuming that the only difference is the code. Even the two code fragments run on the same machine may vary in performance if the machine is under heavy load due to other circumstances. "Premature optimization . . . " - Onorio Catenacci

2 Answers

0
votes

The Pattern match approach would be better for readability as well, not just performance. Running a simplified version with Benchee

iex(4)> Benchee.run(%{                                                          
...(4)> "match" => fn -> [a,b,c | _] = [1,2,3] end,
...(4)> "enum.split" => fn -> [1,2,3] |> Enum.split(3) end
...(4)> })

Yields that the pattern match is a tad better with a list of 3 elements, longer list's results may be different though

Comparison: 
match           916.17 K
enum.split      846.46 K - 1.08x slower +0.0899 μs

On another note, you could simplify your pattern match to one line function, where you pattern match on the struct and read the values as:

def get_color(%Image{hex: [a,b,c | _]}), do: [a,b,c]
0
votes

The Beauty of Elixir language is Pattern Matching.

Pattern matching approach is the best. When we are using Enum.split, we are accessing Enum module, this will become slower with the increasing length of string.