ImNotAVirus

ImNotAVirus

Hi everyone,

I am working on a project where I have to spawn many processes (50k+).
Each process represents an entity that must move on a map.

The behavior of an entity is simple:

  • Each entity choose a random coordinate in a radius around it.
  • Then it calculates the path to go there
  • Once arrived at destination, it pauses for a random time between 850 and 1150 ms
  • It starts again to choose a random coordinate
  • etc..

The pathfinding algorithm is written in Rust (NIF) for performance reasons


So I started to do my first tests with only 10k processes.
Unfortunately, I found that just having 10,000 processes spawn looking for a path and then waiting was already permanently using between 45-55% CPU on my Windows.
Curiously, when I did my tests on WSL, the same algorithm takes only 5 to 10% of CPU on WSL2.

This huge difference in CPU consumption is the first thing I can’t understand/explain.


I then tried to benchmark my pathfinding function using Benchee to see if that was the source of my problems.

I got theses results:

Name            ips        average  deviation         median         99th %
astar      355.56 K        2.81 μs   ±863.72%        2.20 μs       18.60 μs

According to these results, if I take the average execution time of a function, calling 10,000 times the pathfinding function should take only 28.1ms.

So normally, the CPU should not even reach 1% (except maybe when launching the application).

This is the second thing I don’t understand: why the CPU is permanently busy.


Having never worked with so many processes, I don’t know where to start in order to debug such problems.

The code used for my tests and benchmark is available here: GitHub - ImNotAVirus/elixir_nif_example · GitHub

This code has been simplified to include only the spawn of the 10k processes, the call to the pathfinding function and the pause of workers.

Thanks in advance

Showing Posts 1 to 5

kip

kip

ex_cldr Core Team

The BEAM implements busy wait to deliver a smoother and more predictable responsiveness. There are tuning parameters +sbwt, +sbwtdcpu and +sbwtdio that can change the default behaviour. This gist shows some example usage.

In general, a high reported CPU utilisation does not necessarily mean your system is under stress. Typically you don’t need to apply the tuning parameters. And all other things being equal, 50k processes isn’t at all unreasonable.

mpope

mpope

Instead of long running GenServers, have you considered using short lived Tasks? You can use one GenServer to launch these tasks, or can partition the entities across several if one scheduling GenServer becomes a bottleneck. You’d have to store the state in an ETS table indexed by an ID.

NduatiK

NduatiK

Whoa! This is amazing. I am working on something similar for a Stochastic Processes class. Simulating vehicles for traffic light optimization.

I was planning to use libgraph, but this NIF based approach is getting me thinking about performance at scale. Will things work when I jump to more processes? With NIFs, probably.

Thanks and good luck!


PS. Liveview + Surface + SVGs are amazing! Probably would have gone with elm without it, but so far so good.

ImNotAVirus

ImNotAVirus OP

Thanks for your answers everyone.

I did not know the busy wait of BEAM.
So I tested it by deactivating it and I get slightly better results.

Here is what I got (on Windows):

  • 10,000 workers: between 30 and 35%
  • 50,000 workers: between 45 and 60%
  • 100,000 workers: between 70 and 95% (which causes my CPU to be at 100% sometimes because not only BEAM is running)

Do you think it would be possible to improve this?
I don’t know if it’s possible but having 50k proccess under 20% CPU and 100k under 50% would be perfect (or at least be able to run 100k processes without reaching 100%).

ImNotAVirus

ImNotAVirus OP

That was one of the first things I thought of. But the problem is that the entities will have to be able to interact with each other later on (for example if one of them enters the field of action of another one).

That’s why I preferred to make one GenServer per entity.

— All posts loaded —

Where Next? Top

Trending in Questions Top

katta
I having some trouble figuring out if I have set myself too strict of standards for my production server. Currently I can handle 75% of r...
New
peck
Hi everyone. My team and I have been working on a fairly modest app based around video streaming and chat, but we’ve landed a customer t...
New
achenet
Hello, I’m trying to build a basic Phoenix web-app, and I’d like to use Tailwind. However, when I launch mix phx.server, I get an error...
New
bradley
I really like the adapter patterns that ecto, nebulex, waffle, etc. use and would love find something similar for a key management servic...
New
unaware8150
Hello folks! So at work, we are seeing some situations where we have to define some “fixed” strings that are used across the codebase in...
New
Alvinkariuki
How Can I Optimise Compile Time Dependencies I have been building an elixir application for about 2 years now. Many modules and files ha...
New

Other Trending Topics Top

budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
mudasobwa
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
juhalehtonen
There has been a thread to discuss the Stack Overflow Developer Survey on this forum every year since 2018, so here’s yet another one for...
New
budgie
I love Elixir. It’s one of 2 programming languages I’ve ever fallen in love with. But I don’t use it anymore. Serverless was the promis...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews