【问题标题】:Why is Elixir's Access behaviour not a protocol?为什么 Elixir 的访问行为不是协议?
【发布时间】:2016-02-15 17:39:20
【问题描述】:

在最新版本的 Elixir 中,Access 不再作为协议实现,而是作为行为实现。据我所知,这种变化是出于开发模式中的性能考虑。

现在,看看实现,我想知道它在内部是如何工作的,以及为什么选择这个实现。正如我们所看到的here,Access 通过底层映射的“__struct__”键调度到一个结构的模块。 AFAICS,这大致类似于 OOP 风格的多态性。关于这个的几个问题:

  1. 为什么会更快?
  2. 与协议相比有哪些缺点?据我所知,它的可扩展性较差。还有其他的吗?
  3. 到目前为止,我只看到了像 GenServer 这样的东西的上下文中的行为,其中回调模块在初始化时被捕获并保存在一个进程中(至少我假设如此)。在这里,Access 行为从数据中获取回调模块。是否有可能为非结构的东西实现这种行为?
  4. 当人们对协议所带来的额外好处不感兴趣时​​,这种调度是否是 Erlang 或 Elixir 中常见的最佳实践?

【问题讨论】:

  • 所以,不是答案,但有一个 Elixir 核心邮件列表(在 Google 网上论坛上)可能有助于回答您的问题。
  • 扫描那里的主题,看起来这可能不是正确的列表。那里的人讨论核心语言建议,而我的问题更多是关于风格的初学者问题。我真的不想用这个向列表发送垃圾邮件。不过,原则上是个好主意。我可能会将其发布到不同的长生不老药相关列表中。
  • 如果你想知道设计中的决定,那么你需要 Elixir 核心邮件列表。我的意思是,如果在任何时候都将讨论使用将 Access 从协议更改为行为的原因以及该更改的其他属性 - 它会在该邮件列表中。
  • @MigratoryMonkeyMaster 你看过相关的 Github 问题吗? Jose 很好地解释了原因:github.com/elixir-lang/elixir/issues/2973
  • @PatrickOscity,感谢您指出这一点。这肯定是一本有趣的书。但是 AFAICS 的讨论主要关注改变的原因,并没有解释为什么选择这个特定的实现,所以它并没有真正解决我的问题的核心。

标签: elixir


【解决方案1】:

正如您已经提到的,Access 的实现已更改为使用行为而不是协议。原因是性能。

  • 协议是基于类型/数据的多态性,是 Elixir 独有的。这意味着它可以让您根据数据结构进行调度
  • 行为是一种无类型机制,它不依赖于数据结构,而是依赖于模块作为参数。它们也直接内置在 Erlang/OTP ecosystem 中,并且性能更高。

虽然协议在根据数据类型进行调度时为您做了很多繁重的工作,但由于它们的实现方式(整合),它们仍然会为Access 提供never be fast enough

因此,尽管当您需要将某些功能绑定到数据结构而不是模块时,您应该始终使用协议,但Access 是一种特殊情况。

由于Access协议在开发和测试模式下依赖于代码服务器(当没有应用协议合并时),我们已经听到多起报告称,由于代码服务器成为多进程的瓶颈,系统性能受到很大影响.

发生这种情况是因为 Access 协议最终会被调用数千次,而我们无能为力来改进它(与大多数列表案例都内联的 Enumerable 协议相反)。

~Jose Valim


进一步阅读:

【讨论】:

    猜你喜欢
    • 2016-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-04
    • 2017-10-02
    • 2011-04-28
    相关资源
    最近更新 更多