So, in interest of matching this code I wrote an example of spawning 1_000_000 processes that each wait for 3 seconds and then exit.
This is Elixir, but this is trivial to do on the BEAM and could easily be done in Erlang as well:
#!/usr/bin/env elixir
[process_count | _] = System.argv()
count = String.to_integer(process_count)
IO.puts "spawning #{count} processes"
1..count
|> Enum.map(fn _c ->
Task.async(fn ->
Process.sleep(3_000)
end)
end)
|> Task.await_many()
The default process limit is 262,000-ish for historical reasons but it is easy to override when running the script: » time elixir --erl "+P 1000001" process_demo.exs 1000000
spawning 1000000 processes
________________________________________________________
Executed in 6.85 secs fish external
usr time 11.79 secs 60.00 micros 11.79 secs
sys time 15.81 secs 714.00 micros 15.81 secs
I tried to get dotnet set up on my mac to run the code in your example to provide a timing comparison, but it has been a few years since I wrote C# professionally and I wasn't able to quickly finish the required boilerplate set up to run it.Ultimately, although imo the BEAM performs quite well here, I think these kind of showy-but-simple tests miss the advantages of what OTP provides: unparalleled introspection abilities in production on a running system. Unfortunately, it is more difficult to demonstrate the runtime tools in a small code example.