lalo2302

lalo2302

Agent vs Registry

Hi guys!

I am facing a problem where I need to spawn multiple processes, and I have to keep a counter about every process. The counter needs to be indepent and accesing it should not interfiere with the process performance.

Saying this, I am exploring the options of Agent vs Registry.

If I use the Agent module, I would register an Agent for each process :via a Registry.

But how should this be different from only using a Registry, with the register function and the counter as a value.

Isn’t a registry the same as an Agent in that case?

Later today I’ll benchmark it, but wanted to know what do you think. I’ll post my results below.

Have a nice day!

Marked As Solved

CptnKirk

CptnKirk

I would also recommend looking into GenStage for this. You don’t have a tell/ask problem. You want to limit the rate at which you get told something to the amount of capacity you have to process those tells.

This is what GenStage does. You advertise that you’re able to handle some number of events, and then you eventually get at most that number. Once you decide you can handle more events, you advertise that you’re able to handle more. This is all done more or less transparently for you by GenStage.

As you’ve already discovered, architecting a solution to your problem with Process.info doesn’t work well.

Consider using GenStage to solve your rate problem. Then within GenStage, delegate to a module that is focused on data processing. This way you’ve separated your business problem from your rate problem. And you can test your business module easily.

Agents and Registries aren’t required here. Although you’re free to register your GenStage processes with a Registry and/or hold state within an Agent. Up to you, they are different tools for different problems.

Edit: You may also want to look at Flow. Flow helps to provide a higher level data flow/processing abstraction, so you don’t need to worry about implementing a GenStage. If your workers are mapping or reducing something, then Flow could be a great fit.

Also Liked

josevalim

josevalim

Creator of Elixir

You are already making a big assumption that you will need processes. Could you please tell us about the problem you want to solve in general and why did you arrive to the conclusion that you need processes?

Why are you keeping count of how much work a process has done? Why not have a single process that does a single work and then dies?

peerreynders

peerreynders

I think the answer to your problem is another process which is only responsible for the counter.

  • The process doing the work notifies its counter process when the count is updated
  • Other processes call the counter process to obtain the current state.

Alternately it may make more sense for the counter process to be subscription based - otherwise you are building an “ask architecture” rather than a “tell architecture” (Tell, Don’t Ask).

Personally Agents make me queasy because anybody can mess with their internal state which has the smell of “global mutability”.

Registry pubsub may be an interesting option - though I haven’t looked at it in detail (if I’m reading the source correctly, dispatch/4 will run in the calling process rather than queuing the function to be executed later within the registry’s process, so I would classify this approach as “interfering with process performance”).

LostKobrakai

LostKobrakai

This sounds like a job for GenStage and not the mailbox queue.

peerreynders

peerreynders

It may make more sense to organize it a bit differently along the lines of Building Non Blocking Erlang apps:

  • The actual work is being done by a short-lived process (perhaps Task processes) that send the result to the parent process when they are done.
  • The parent process will aways accept a new request but may queue a request if the maximum number of child processes is currently running. The parent process can block the requesting process while this is going on.
  • As child processes complete requests are pulled off the parent’s internal queue to launch fresh child processes.

GenStage.ConsumerSupervisor does something similar but you may need a solution adapted to your particular requirements. Also have a look at Task.Supervisor just so you know what is available.

CptnKirk

CptnKirk

I’m not exactly sure what you mean here. Do you mean that you need to keep a total count of your workers? Or that each worker needs to keep an independent counter of something?

If you simply need to keep track of your worker totals, you might consider using a custom Supervisor or DynamicSupervisor. You’d use the Supervisor to spawn and watch your workers for failures. Supervisors also keep a count of their children, so you’d get a global worker count for free, without impacting the work being done within the workers.

Supervisors - spawn and monitor children for failures, restarting them if necessary
Agents - store and mutate local state
Registries - keep track of a mapping from a name → pid

Both Registries and Supervisors support a count. Supervisors will help you keep your workers alive. Registries will help you find and communicate with multiple workers. However, if a worker dies, it’ll be removed from the registry without any attempts at restarting.

Where Next?

Popular in Questions Top

shahryarjb
Hello, I get Persian date from my client and convert it to normal calendar like this: def jalali_string_to_miladi_english_number(persi...
New
sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
yawaramin
In the Dialyzer docs ( http://erlang.org/doc/man/dialyzer.html#requesting-or-suppressing-warnings-in-source-files ), there is a way to tu...
New
lk-geimfari
What is most correct way to open, read and parse JSON file with poison? For example if we have example.json file in root of some projec...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
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
Codball
Mix format works fine if run from the cmd. I’ve followed this to facilitate the implementation into VSC which involves downloading an ext...
New
Mooodi
Given a string, how can I get access to its character by index? Enum.at("my_string", 2) doesn't work. Or rather, not char, but a substr...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New

Other popular topics Top

joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 record...
New
ycv005
I have followed this StackOverflow post to install the specific version of Erlang. And When I am running mix ecto.setup then getting fol...
New
Jim
As a follow up to my earlier question: I have the code compiling and running but not getting a successful login from the rest server. ...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
chrismccord
As promised, the first release candidate of Phoenix 1.3.0 is out! This release focuses on code generators with improved project structure...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
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
josevalim
Hi everyone, One of the features added to Elixir early on to help integration with Erlang code was the idea of overridable function defi...
New
AstonJ
by Lance Halvorsen Elixir and Phoenix are generating tremendous excitement as an unbeatable platform for building modern web application...
460 27162 124
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New

We're in Beta

About us Mission Statement