Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is Elixir's Access behaviour not a protocol?

Tags:

elixir

In recent versions of Elixir, Access is no longer implemented as a protocol, but as a behaviour. From what I gather, this change was motivated by performance considerations in development mode.

Now, looking at the implementation, I wonder how this works internally and why this implementation was chosen. As we can see here, Access dispatches to a struct's module via the underlying map's "__struct__" key. AFAICS, this roughly works like OOP-style polymorphism. A few questions about this:

  1. Why is this faster?
  2. What are the downsides compared to Protocols? From what I can tell it is less extensible. Are there other?
  3. So far I have only seen behaviours in the context of stuff like GenServer, where the callback module is captured at initialization and kept in a process (At least I assume as much). Here, the Access behaviour grabs the callback module from the data. Would it even be possible to implement this behaviour for something that is not a struct?
  4. Is this kind of dispatch a common best practice in Erlang or Elixir when one is not interested in the added benefit that a Protocol would give?
like image 283
MigratoryMonkeyMaster Avatar asked Nov 14 '15 02:11

MigratoryMonkeyMaster


1 Answers

As you've already mentioned, Access's implementation was changed to use Behaviours instead of Protocols. The reasoning was performance.

  • Protocols are type/data based polymorphism, and are exclusive to Elixir. That means it lets you dispatch based on the data structure
  • Behaviours are a typeless mechanism that don't rely on a data structure, but the module as an argument. They're also built right into the Erlang/OTP ecosystem and are much more performant.

While Protocols do a lot of the heavy lifting for you when dispatching based on data types, they will still never be fast enough for Access because of the way they're implemented (consolidation),

So although you should always use Protocols when you need to tie some functionality to a data structure rather than a Module, Access is a special case.

Because the Access protocol relies on the code server in development and test mode (when protocol consolidation is not applied), we have heard multiple reports of the system suffering greatly in performance as the code server becomes a bottleneck with multiple processes.

This happens because the Access protocol ends up being invoked thousands of times and there isn't much we can do to improve it (in contrast to the Enumerable protocol where most of the list cases are inlined).

~ Jose Valim


Further Reading:

  • Github: Get rid of the Access Protocol
  • Elixir Forum: Why is Access a Behaviour instead of a Protocol
  • Stackoverflow: Difference between Protocol & Behaviour in Elixir
  • Mailing List: Understanding Protocols vs. Behaviours
  • Blog post: Behaviours vs. Protocols
like image 81
Sheharyar Avatar answered Oct 15 '22 05:10

Sheharyar