Qqwy

Qqwy

TypeCheck Core Team

When to use OTP vs 'bare' processes?

The more I read about Elixir’s and Erlang’s actor-model-based functionality, the more I am in love.

One thing I am wondering about, is when it is better to drop down to a ‘bare’ recieve-loop, over spawning something as a GenServer?

GenServer, Agent and friends do a lot of the behind-the-scenes work for you, but are there any drawbacks to using them that would make it better to use bare processes in some cases?

Most Liked

sasajuric

sasajuric

Author of Elixir In Action

All of the processes which are started directly from the supervisor should be OTP compliant (aka special processes). This will allow them to work properly within the supervision tree, and to play nice with tools/modules such as observer, sys, dbg, …

Abstractions such as GenServer, Supervisor, but also Agent and Task are already OTP compliant. If none of them suit your needs, you could implement your own OTP compliant behaviour. Usually, it’s easiest to do this on top of an existing OTP compliant behaviour. For example, Supervisor, Agent, and gen_fsm are internally powered by GenServer (or gen_server).

If none of the existing behaviours serve as a good baseline, then you have to start from scratch and support all OTP requirements as explained in the link above. The core library by @fishcakez could simplify the task.

One advantage of rolling an OTP compliant process from scratch is that you can do selective receives. In other words, you can use pattern matching in receive to give higher priority to some types of messages. This is something that doesn’t work with GenServer.

To be honest, I never used this technique myself. In the singe case where I had this need, I just split GenServer in two processes. One process received messages from clients, and acted as a priority queue. Another process was the consumer that handled messages. The consumer would ask for the next message from a queue, and then handle the message. Meanwhile the queue can accept subsequent messages and rearrange them by priority. When the consumer is done with the current message, it asks the queue for the next one, and it gets the one with the highest priority. I guess this approach can have perf/latency issues with a large rate of incoming messages, and then perhaps a manual loop with a selective receive might help. But as I said, even with this approach, it’s best to make such process OTP compliant.

15
Post #5
dom

dom

Cowboy, the erlang web server that powers Phoenix, uses special processes in several places. Loïc has some excellent content covering the why and how on his website:

JEG2

JEG2

Author of Designing Elixir Systems with OTP

I feel the answer is probably, “not too often.” Maybe if you are building trivial tools it’s fine, but for most serious projects I believe you want to be favoring OTP construction.

spawn(), send(), and receive() are basic building blocks. OTP uses them under the hood and it’s useful to learn a bit about them to help you understand the higher layers.

However, you probably don’t often fire up a telnet client to check your email. You could, assuming you know the protocol commands to send, but doing so is harder and more error prone.

Last Post!

Azolo

Azolo

Indeed, you are right. I wonder why I got so confused about.

Maybe it was just because none of the gen processes look up the pdict, they keep track of their parents in their loops.

Maybe I just thought there was some grander purpose and the pdict lookup wasn’t always reliable.

Where Next?

Popular in Questions Top

Emily
I have VueJS GUIs with the project generated using Webpack. I have Elixir modules that will need to be used by the VueJS GUIs. I forese...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New

Other popular topics Top

nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
chrismccord
Phoenix 1.4.0 released Phoenix 1.4 is out! This release ships with exciting new features, most notably with HTTP2 support, improved deve...
688 31586 112
New
AngeloChecked
What learn first? Rust or Elixir Hi Elixir community! I’m here because i want learn a new language. I’m a junior developer and mainly i ...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
AstonJ
Posting this to see if we can make things easier for people to get into Neovim. If you use Neovim and have a favourite distro please let ...
New

We're in Beta

About us Mission Statement