【问题标题】:Is pattern matching better than Enum.split?模式匹配比 Enum.split 更好吗?
【发布时间】:2019-04-16 07:53:41
【问题描述】:

我想在我的函数get_color(image) 中获取 Elixir 字节列表中的前 3 个字节,其中 image 是一个结构体,hex 定义为字节列表。

现在我知道这种模式匹配方式是这样的:

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

我的初始代码是:

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

我想知道这两种方法是否同样有效,或者 Enum.split 是否有其他一些可能使其变慢的后台工作?或者它可能会消耗更多内存,因为它还必须创建列表的另一半?

我的代码的基准测试(基于答案):

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

【问题讨论】:

  • 询问这两种方法是否“同样有效”是假设 only 区别在于代码。如果机器由于其他情况而处于重负载状态,即使是在同一台机器上运行的两个代码片段也可能会在性能上有所不同。 “过早的优化……”

标签: elixir


【解决方案1】:

模式匹配方法在可读性方面也会更好,而不仅仅是性能。使用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)> })

如果使用 3 个元素的列表,模式匹配会更好一些,但更长的列表的结果可能会有所不同

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

另一方面,您可以将模式匹配简化为一个行函数,您可以在其中pattern match on the struct 并将值读取为:

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

【讨论】:

  • 感谢您的示例!
【解决方案2】:

Elixir 语言的美妙之处在于模式匹配

模式匹配方法是最好的。当我们使用 Enum.split 时,我们正在访问 Enum 模块,这会随着字符串长度的增加而变慢。

【讨论】:

  • 所以访问模块比较慢?我认为这些功能无论如何都是可用的。
  • 不完全是。是的。
  • 你可以查看here幕后发生的事情
  • Elixir 提供宏作为元编程(编写生成代码的代码)的机制。宏在编译时展开。
  • 模块中的公共函数全局可用
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-09-22
  • 1970-01-01
  • 2022-08-06
  • 1970-01-01
  • 2015-07-21
  • 2019-11-05
  • 2010-09-14
相关资源
最近更新 更多