Comment by notpushkin
Comment by notpushkin 2 months ago
Note that this uses (I hope!) Erlang processes, which are not to be confused with OS processes.
Comment by notpushkin 2 months ago
Note that this uses (I hope!) Erlang processes, which are not to be confused with OS processes.
.Net uses real OS threads and that 4mb is the stack not the heap which must be allocated on thread creation. The heap is shared in the process amongst all the threads whereas Erlang is separate lightweight green thread/processes with dynamic heap and stack per process.
.Net originates in the Windows world where new processes are expensive but threads are much cheaper however they still use native stacks for iterop and hardware protection, stack must be contiguous so it is fixed at thread creation this is typical for all native os threads.
Erlang is a VM and runs on top of of processes and threads but exposes its own process model to the language that does not map 1:1 and therefore does not have a fixed stack size allowing many light weight processes. It pays an indirection penalty in performance for this but allows some nice stuff.
Java started with green threads and abandoned them, both .Net and Java use asynchronous concepts instead to get high concurrency now days cooperatively releasing threads and rentering them. There was talk of trying green threads out in .Net and bringing them back in Java for ergonomics compared to async, these green threads would not have such large fixed stacks and many more could be made similar to Erlang processes.
In the end, .NET is going hybrid route. Circa .NET 10/11 Roslyn will stop emitting state machines and something state-machine-like will be produced by the compiler itself iff the asynchronous execution suspends, and will be otherwise practically free.
https://github.com/dotnet/runtime/blob/main/docs/design/spec...
Mind you, short-lived operations are much cheaper with stackless co-routine model like in C#/F# or Rust than spawning an entire, even if virtual, thread/process.
I get why they went the async route due to performance implications and such, just like the old cooperative multi-tasking days everything was much lighter weight but one misbehaved process not yielding can block the whole OS.
Nice to see further improvement coming along in .Net however I conceptually prefer the everything is a lightweight process model to this function coloring async virus that invades the codebase now days, wouldn't be so bad if it had been easy to do sync over async from the beginning without caveat in .Net so you didn't need to have dual sync and async api all the way down the stack.
The unit of comparison with BEAM processes are .NET tasks. The results are much less favorable to Erlang or Elixir in that case
https://gist.github.com/neon-sunset/8fcc31d6853ebcde3b45dc7a...
Yep. I researched JVM and .NET thread sizes once, to compare/contrast with Erlang processes, and the difference is ludicrous.
Erlang: ~1k
64-bit .NET thread: 4MB