# Pool of Processes vs One Process

**URL:** <https://erlangforums.com/t/pool-of-processes-vs-one-process/870>\
**Category:** Questions / Help\
**Tags:** erlang-otp\
**Created:** [December 25, 2021, 6:04pm UTC](https://erlangforums.com/t/pool-of-processes-vs-one-process/870 "2021-12-25T18:04:30Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Abdelghani](https://erlangforums.com/letter_avatar_proxy/v4/letter/a/49beb7/32.png) [@Abdelghani](https://erlangforums.com/u/Abdelghani)\
**Post date:** [December 25, 2021, 6:04pm UTC](https://erlangforums.com/t/pool-of-processes-vs-one-process/870/1 "2021-12-25T18:04:30Z")

</div>

Hi everybody, it’s recommended to use a pool of Erlang Processes that are ready to `accept` connections on a Listen Socket and that’s what “Joe Armstrong” said too in his manual book, and the benefits are to doing PARALLEL `accept` at the same time.

But when we look so deeply in this method, a Listen Socket is an Erlang Port and when Erlang Processes that are distributed across Schedulers Threads (SMP) do `gen_tcp:accept(ListenSocket)`, they try to communicate with the Port (ListenSocket) that results in running the Network Driver, and this Port as all Erlang Ports is protected by a LOCK and can be used by just one Thread at a time and all calls to this Port will be executed in fact in SEQUENCE.

So why using a pool of Processes that `accept` connections instead of using just one Process that `accept` and `spawn` it’s Alternative ?

My searches about this starts from analyzing the source code of `ejabberd` Server that use just one Process to `accept` connections.

---

<div class="post-metadata">

**Author:** ![domi](https://erlangforums.com/user_avatar/erlangforums.com/domi/32/263_2.png) [@domi](https://erlangforums.com/u/domi)\
**Post date:** [December 26, 2021, 6:54am UTC](https://erlangforums.com/t/pool-of-processes-vs-one-process/870/2 "2021-12-26T06:54:06Z")

</div>

To spawn the process the acceptor has to call a supervisor, which does the actual spawn, waits for the init callback to return, logs progress reports, and updates its internal state. This blocks the acceptor for a while, so it’s worth using multiple acceptors and supervisors to ensure other connections can still be accepted while this is happening.

---

<div class="post-metadata">

**Author:** ![Abdelghani](https://erlangforums.com/letter_avatar_proxy/v4/letter/a/49beb7/32.png) [@Abdelghani](https://erlangforums.com/u/Abdelghani)\
**Post date:** [December 26, 2021, 3:10pm UTC](https://erlangforums.com/t/pool-of-processes-vs-one-process/870/3 "2021-12-26T15:10:11Z")

</div>

So the thing maybe in the code after the `gen_tcp:accept()` call 🤔 ,but in practice all acceptors share the same `simple_one_for_one` supervisor and each `accept` results in `supervisor:start_child(SharedSup, [])` (Cowboy works similarly), and in fact I don’t know if spawning Childs from the same Supervisor can be done in PARALLEL but if not and it’s done in SEQUENCE I think logging and other things are very fast and negligibles.

---

<div class="post-metadata">

**Author:** ![domi](https://erlangforums.com/user_avatar/erlangforums.com/domi/32/263_2.png) [@domi](https://erlangforums.com/u/domi)\
**Post date:** [December 27, 2021, 12:38am UTC](https://erlangforums.com/t/pool-of-processes-vs-one-process/870/4 "2021-12-27T00:38:15Z")

</div>

Modern Cowboy uses multiple supervisors, in fact it can even use multiple sockets (on the same port). See:

[https://ninenines.eu/articles/ranch-2.0.0/](https://ninenines.eu/articles/ranch-2.0.0/)

---

<div class="post-metadata">

**Author:** ![Abdelghani](https://erlangforums.com/letter_avatar_proxy/v4/letter/a/49beb7/32.png) [@Abdelghani](https://erlangforums.com/u/Abdelghani)\
**Post date:** [December 27, 2021, 1:10am UTC](https://erlangforums.com/t/pool-of-processes-vs-one-process/870/5 "2021-12-27T01:10:52Z")

</div>

Exactly, I have read the code of `ranch_acceptors_sup` but not the code of `ranch_conns_sup` and this explains why there is `ranch_conns_sup_sup` so now I confirmed where is the Parallel handling in accepting connections, Thank you @domi for your “links” that explain always directly what I search about, I know about many Listen Sockets with the same port number, it lasts just one question that you shouldn’t answer if you want, why ejabberd (know of it’s powerful performance and scalability) use just one process to accept connections(I confirmed by reading latest version of code)?

---

<div class="post-metadata">

**Author:** ![domi](https://erlangforums.com/user_avatar/erlangforums.com/domi/32/263_2.png) [@domi](https://erlangforums.com/u/domi)\
**Post date:** [December 27, 2021, 2:44am UTC](https://erlangforums.com/t/pool-of-processes-vs-one-process/870/6 "2021-12-27T02:44:08Z")

</div>

I’m not familiar with it, but I would guess its connections usually live for a long time, so the accept rate isn’t a bottleneck.

---

<div class="post-metadata">

**Author:** ![Abdelghani](https://erlangforums.com/letter_avatar_proxy/v4/letter/a/49beb7/32.png) [@Abdelghani](https://erlangforums.com/u/Abdelghani)\
**Post date:** [December 27, 2021, 3:09am UTC](https://erlangforums.com/t/pool-of-processes-vs-one-process/870/7 "2021-12-27T03:09:36Z")

</div>

This is exactly what I doubted, since “http” restarts the connection each time, the `accept` have heavy impact to performance comparing with “xmpp”, Thank you @domi for all.

---

<div class="post-metadata">

**Author:** ![juhlig](https://erlangforums.com/user_avatar/erlangforums.com/juhlig/32/837_2.png) [@juhlig](https://erlangforums.com/u/juhlig)\
**Post date:** [December 27, 2021, 9:31pm UTC](https://erlangforums.com/t/pool-of-processes-vs-one-process/870/8 "2021-12-27T21:31:52Z")

</div>

> [@Abdelghani](#):
>
> So why using a pool of Processes that `accept` connections instead of using just one Process that `accept` and `spawn` it’s Alternative ?

There is another point besides performance that should be noted here, which is the separation of accepting from connection handling.

Ranch, the acceptor component of cowboy, has acceptors, ie `ranch_acceptor` processes that do nothing much but running `accept` in a loop. If a connection is thus accepted, the acceptor process tells its associated `ranch_conns_sup` to start a connection handling process, and hands the connection off to it. It doesn’t matter to the acceptor process whether the connection process runs, crashes, or doesn’t even start. And even if an acceptor process crashes, the `ranch_acceptors_sup` above it will restart it and everything will just continue working as before.

An approach in which a process accepts and spawns a new acceptor is more fragile. The chain breaks/ends if the current acceptor crashes at any point before it can spawn a new acceptor.

---

<div class="post-metadata">

**Author:** ![Abdelghani](https://erlangforums.com/letter_avatar_proxy/v4/letter/a/49beb7/32.png) [@Abdelghani](https://erlangforums.com/u/Abdelghani)\
**Post date:** [December 28, 2021, 10:35am UTC](https://erlangforums.com/t/pool-of-processes-vs-one-process/870/9 "2021-12-28T10:35:10Z")

</div>

Thank you for that @juhlig , I didn’t read the entire code of Cowboy but Iam in progress, yes that is there are acceptors and conns\_sup and each acceptor has it’s conns\_sup, but I can’t understand how it works exactly until I read the source, there is another thing that I noted : why using the Erlang processes implementation (spawn, receive, Pid !,…) instead of the OTP recommended implementation(gen\_server)?

---

<div class="post-metadata">

**Author:** ![AstonJ](https://erlangforums.com/user_avatar/erlangforums.com/astonj/32/9_2.png) [@AstonJ](https://erlangforums.com/u/AstonJ)\
**Post date:** [December 28, 2021, 5:11pm UTC](https://erlangforums.com/t/pool-of-processes-vs-one-process/870/10 "2021-12-28T17:11:19Z")

</div>

> [@Abdelghani](#):
>
> why using the Erlang processes implementation (spawn, receive, Pid !,…) instead of the OTP recommended implementation(gen\_server)?

Without reading the code I would guess in those cases a simple spawn was sufficient.

From looking at some of your threads here it sounds like you would benefit from reading a couple of Erlang books. In Elixir in Action (and I am sure many Erlang books cover similar) there is discussion about some of this. Here’s what I had written in my review:

> Saša also covers much more than just the fundamentals of the language; after the basics you cover processes and OTP in quite some detail (and from what I’ve read so far, goes into more detail here than PE). You actually build your own server process before he introduces you to GenServers (which I felt was an excellent way to demystify them) - you’ll definitely leave feeling as though you have a fantastic insight into Elixir and Erlang!

I haven’t read it yet but I imagine [Erlang and OTP in Action](https://erlangforums.com/t/erlang-and-otp-in-action-manning/325) covers similar if not more. Books are incredibly useful in helping you get a good understanding of a language and what’s possible with them. You can even get 35% off using our discount code :003:

---

<div class="post-metadata">

**Author:** ![Abdelghani](https://erlangforums.com/letter_avatar_proxy/v4/letter/a/49beb7/32.png) [@Abdelghani](https://erlangforums.com/u/Abdelghani)\
**Post date:** [December 28, 2021, 6:06pm UTC](https://erlangforums.com/t/pool-of-processes-vs-one-process/870/11 "2021-12-28T18:06:06Z")

</div>

Thank you @AstonJ I have read some of Erlang’s books and I did just a look at some others, but if you note too that all books share the same strategy to explain the language and there is no one (that I looked for) contains internal details, for example will be recommended to use a pool of processes but never find why and where is the parallel and the sequential parts in accepting connections as it aswered here, an other example there is no book absolutely describes in details internal ERTS and Beam, I find one on github that many important chapters are missing… so I think that there is no more benefits from reading books at this stage.  
Ok returning to the question, and as you said basing on books recommandations this is what I found in “Erlang Programming” by Francesco Cesarini &  
Simon Thompson 🤔  
“One of the downsides of OTP is the layering that the various behavior modules require. This will affect performance. In the attempt to save a few microseconds from their calls, developers have been known to use  
the Pid ! Msg construct instead of a gen\_server cast, handling their messages in the handle\_info/2 callback.  
Don’t do this! You will make your code impossible to support and maintain, as well as losing many of the advantages of using OTP in the first place. If you are obsessed with saving microseconds, try to hold on  
and optimize only when you know your program is not fast enough”,  
And 🙂 ?

---

<div class="post-metadata">

**Author:** ![starbelly](https://erlangforums.com/user_avatar/erlangforums.com/starbelly/32/209_2.png) [@starbelly](https://erlangforums.com/u/starbelly)\
**Post date:** [December 28, 2021, 6:07pm UTC](https://erlangforums.com/t/pool-of-processes-vs-one-process/870/12 "2021-12-28T18:07:25Z")

</div>

I’d like to piggy back on this by saying Joe hated the words parallel and simultaneous 🙂

[![](https://img.youtube.com/vi/bo5WL5IQAd0/maxresdefault.jpg "How we program multicores - Joe Armstrong") ](https://www.youtube.com/watch?v=bo5WL5IQAd0)

---

<div class="post-metadata">

**Author:** ![Abdelghani](https://erlangforums.com/letter_avatar_proxy/v4/letter/a/49beb7/32.png) [@Abdelghani](https://erlangforums.com/u/Abdelghani)\
**Post date:** [December 28, 2021, 6:08pm UTC](https://erlangforums.com/t/pool-of-processes-vs-one-process/870/13 "2021-12-28T18:08:37Z")

</div>

@starbelly you are outside the subject Amigo 😄 😄 😄 😄

---

<div class="post-metadata">

**Author:** ![starbelly](https://erlangforums.com/user_avatar/erlangforums.com/starbelly/32/209_2.png) [@starbelly](https://erlangforums.com/u/starbelly)\
**Post date:** [December 28, 2021, 6:14pm UTC](https://erlangforums.com/t/pool-of-processes-vs-one-process/870/14 "2021-12-28T18:14:40Z")

</div>

I disagree. The word parallel keeps coming up and I provided a fun fact around what one of the creators of the language thought about said word, especially in the context of Erlang/OTP but also in general 🙂

---

<div class="post-metadata">

**Author:** ![juhlig](https://erlangforums.com/user_avatar/erlangforums.com/juhlig/32/837_2.png) [@juhlig](https://erlangforums.com/u/juhlig)\
**Post date:** [December 28, 2021, 10:22pm UTC](https://erlangforums.com/t/pool-of-processes-vs-one-process/870/15 "2021-12-28T22:22:38Z")

</div>

> [@Abdelghani](#):
>
> I didn’t read the entire code of Cowboy

You’re mixing things here. If we talk about accepting connections, we’re talking about Ranch, not Cowboy. While Cowboy is the reason behind the existence of Ranch, and in fact the acceptor logic was completely built into Cowboy in the beginning, it was later separated out and moved into an own project, as Ranch can do more/other things than just accept connections _for Cowboy_.  
For example, [gen\_smtp](https://github.com/gen-smtp/gen_smtp) uses it to accept connections for SMTP, and RabbitMQ uses it to accept connections for AMQP, its REST API, and web interface (the latter then work via Cowboy).

> [@Abdelghani](#):
>
> why using the Erlang processes implementation (spawn, receive, Pid !,…) instead of the OTP recommended implementation(gen\_server)?

Hm, now that you’re asking, I noticed that I never asked that question in all the time I was doing stuff for Ranch 😅 Btw, `ranch_conns_sup` acts as a _supervisor_, not a gen\_server. Then again a supervisor _is_ a gen\_server, so you’re not entirely off 😉

But to answer your question (as far as (I think) I know), `ranch_conns_sup` needs to do some things that can’t be done with a standard supervisor, or would require a quite complex (and more fragile) setup with extra processes for management and bookkeeping etc.  
On the other hand, there is a lot in the standard supervisor which `ranch_conns_sup` just does _not need_ and which could therefore simply be left out at the same time, resulting in small performance gains, but those were not the reason for the custom implementation, they just happened to come as a plus, for free.

---

<div class="post-metadata">

**Author:** ![juhlig](https://erlangforums.com/user_avatar/erlangforums.com/juhlig/32/837_2.png) [@juhlig](https://erlangforums.com/u/juhlig)\
**Post date:** [December 28, 2021, 10:36pm UTC](https://erlangforums.com/t/pool-of-processes-vs-one-process/870/16 "2021-12-28T22:36:43Z")

</div>

> [@AstonJ](#):
>
> I haven’t read it yet but I imagine [Erlang and OTP in Action](https://erlangforums.com/t/erlang-and-otp-in-action-manning/325) covers similar if not more.

Funny that you should mention _that_ book 😄 Because in one chapter, they build a TCP server (I forgot what for, though), using just the aforementioned naive accept+spawn approach 😅

The [socket chapter of Learn You Some Erlang](https://learnyousomeerlang.com/buckets-of-sockets#sockserv-revisited) highlights the shortcomings of this approach in terms of performance, and proposes a different (but really very similar) approach with better performance.

---

<div class="post-metadata">

**Author:** ![Abdelghani](https://erlangforums.com/letter_avatar_proxy/v4/letter/a/49beb7/32.png) [@Abdelghani](https://erlangforums.com/u/Abdelghani)\
**Post date:** [December 29, 2021, 2:35am UTC](https://erlangforums.com/t/pool-of-processes-vs-one-process/870/17 "2021-12-29T02:35:51Z")

</div>

@juhlig you have write a lot but you didn’t answer the question 😅, Ranch is a Network Layer Server and Cowboy is An Application Layer Server so we can use any Application Server on top of Ranch, my question was why using the Erlang implementation instead of the OTP implementation, all recommandations from Joe and others said that should always use the generic server (when I said `gen_server` in my previous post I mean using `gen_server` instead of the process created by `proc_lib:start_link` I didn’t mean `ranch_conns_sup` so should read correctly my post) and I have posted a note from well know book previously, and also the example from the book you mentioned (I read it a long time ago, you should read it before talk about) use a `gen_server` acceptor so why Cowboy don’t use ?  
I think to gain some performance taking off `gen_server` additional overload as you said, if this is the case why we don’t all just taking off overload and taking off the OTP implementation ? in other terms when to be better to use `proc_lib` and when to be better to use `gen_server` ? this question is not easy to answer

---

<div class="post-metadata">

**Author:** ![starbelly](https://erlangforums.com/user_avatar/erlangforums.com/starbelly/32/209_2.png) [@starbelly](https://erlangforums.com/u/starbelly)\
**Post date:** [December 29, 2021, 2:44am UTC](https://erlangforums.com/t/pool-of-processes-vs-one-process/870/18 "2021-12-29T02:44:47Z")

</div>

> [@Abdelghani](#):
>
> all recommandations from Joe and others said that should always use the generic server (when I said `gen_server`

When did Joe say this? Who else who has said this? You should always **prefer** to use behaviors provided by OTP, such as `gen_server` but there is no hard and fast rule. There’s always going to be a case where the general case may be sub-optimal for your needs. That said and iirc per conversations with others, performance was a reason at one point for such a design decision, but that is no longer true AFAIK (i.e., you don’t get much of a performance gain from avoiding gen\_server these days).

“Make it work, then make it beautiful, then if you really, really have to, make it fast. 90 percent of the time, if you make it beautiful, it will already be fast. So really, just make it beautiful!” – Joe Armstrong

---

<div class="post-metadata">

**Author:** ![AstonJ](https://erlangforums.com/user_avatar/erlangforums.com/astonj/32/9_2.png) [@AstonJ](https://erlangforums.com/u/AstonJ)\
**Post date:** [December 29, 2021, 2:51am UTC](https://erlangforums.com/t/pool-of-processes-vs-one-process/870/19 "2021-12-29T02:51:54Z")

</div>

> [@juhlig](#):
>
> Funny that you should mention _that_ book 😄 Because in one chapter, they build a TCP server (I forgot what for, though), using just the aforementioned naive accept+spawn approach 😅

Ah that’s awesome Jan! I really enjoyed the Elixir In Action’s equivalent, so I hope to get around to Erlang and OTP in Action as well one day 😊

> [@starbelly](#):
>
> “Make it work, then make it beautiful, then if you really, really have to, make it fast. 90 percent of the time, if you make it beautiful, it will already be fast. So really, just make it beautiful!” – Joe Armstrong

This!!^^ :003:

---

<div class="post-metadata">

**Author:** ![domi](https://erlangforums.com/user_avatar/erlangforums.com/domi/32/263_2.png) [@domi](https://erlangforums.com/u/domi)\
**Post date:** [December 29, 2021, 3:55am UTC](https://erlangforums.com/t/pool-of-processes-vs-one-process/870/20 "2021-12-29T03:55:10Z")

</div>

Loïc, the author of Cowboy / Ranch, gave a talk about this:

> **[Erlang Factory - Loïc Hoguin, Creator of the Cowboy WebSocket Framework,...](https://www.erlang-factory.com/conference/ErlangUserConference2013/speakers/LoicHoguin)**
>
> Founder of the Nine Nines open source Erlang company. Main author of the
> Cowboy, Bullet, Sheriff and Farwest projects. Spawnfest co-founder and 
> organizer.\<br\>\<br\>Twitter: \<a href="http://twitter.c

[Next page](https://erlangforums.com/t/pool-of-processes-vs-one-process/870.md?page=2)
