Genserver with Task.start adds better concurrency?

I have a noob elixir/phoenix/genserver question. Phoenix can handle request concurrently which I assume would mean it would utilise multiple cores available but genserver processes messages in sequence that would mean it would utilize only a single core. With that uderstanding Lets say I have a phoenix web app that recevices request and publishes messages to PubSub to utilize core efficiently and not have a bottleneck of single genserver messages are split in multiple topics with each topic subscribed by a genserver. This would allow better core utilization but still messages are processed in sequence and each core can have more than 1 thread to run or more cores than the topics available to use. In that case if Task.start is used inside a genserver, assuming genserver is not concerned of the task outcome or completion will that allow better hardware utilisation and more parallel processing ? Are there any performance impact such as context switching etc over single thread genserver processing . I have tried to put what is in my head in the diagram below. Also is there a better way to process messages from pubsub or a better design for this architecture and hardware utilization problem

What are these GenServers doing? I think if you’re a Phoenix noob and are writing GenServers you’re probably doing something wrong, unless they are game rooms.

In general you probably shouldn’t use GenServers to achieve parallel processing, that’s a job for Task.

In the diagram you show you’re adding a “ton of middlemen”. That adds complexity and probably latency. For reference I’ve worked on a 50k+ loc Phoenix app that orchestrated ml applications with a graphql api for internal and a rest API for external clients and we wrote zero GenServers (ofc supervisors and Phoenix and some of the libraries we use work via GenServers, so we were using them we just didn’t write any).

1 Like

trying to use genservers as subscribers to messages being published in pubsub to be acted on. They can be pushed directly to a Task as well but then there will be no control over how many tasks are generated or to add some back pressure if required. Is there a better way to work with pubsub as a subscriber than genserver ? Also trying to understand is using Task in a genserver a valid approach to utilise hardware better than a single threaded genserver. So the question is 2 prong

I’m confused, is there a reason you need to publish it to the pubsub? Why not just run the task from the controller?

1 Like

Can you describe the content of these messages and what you’re doing with them?

That is a possibility but if I have to share messages across nodes won’t pubsub be useful ?

these are incoming messages that need to be sent to a dashboard as a stream , its not a chat app or anything. Each message has to be processed and categorised and then pushed out. Its kind of getting a message do some transformation i suppose and then pushed out.

Process it at ingest and only send a final product out over the pubsub.

1 Like

but who subscribes to the pubusub, publishing to the pubusub is not a problem ? Is there a better option than genserver to use than to roll out a solution ? under the hood that might itself use some kind of a genserver. In which case how to make sure that hardware is used to achieve best possible parallelism.

Your controller is running inside of a GenServer, so in most cases you have all the parallelism you need, one per connection. The Erlang scheduler is plenty good at balancing cores. Don’t reach to optimize for that unless you can prove you need it. If you truly need to close your http connection quickly and don’t mind detaching the computation (fire and forget), spawn Tasks from inside your controller.

1 Like

thanks will think in those terms.