>And the best solution was a solution based on a select/epoll/kpoll loop
But the underlying mechanism does not need to dictate what interface is exposed to be used.
>And it turns out that in most practical application userland threading is actually built on an asynchronous IO select-like call.
That is precisely the point. Presenting it as though the only options are "use native threads" and "use callbacks and event loops" is the myth. Use userland threads, you get the same performance and scalability as an event driven style, as it uses the exact same async calls under the hood, but you get a programming style that is readable and maintainable.
Using an event loop is like rolling your own while loop out of setjmp/longjmp. Yes, the underlying mechanism of a loop is the same, but abstraction is pretty nice.
Because the other side of highly concurrent applications is increase complexity. Both threads and async-based _large_ applications become a mess, fast. No talking about HAProxy type small server, but complicated business rules, state machines and so on. Shared state is hard to reason in non-concurrent application, large concurrent ones, especially with shared data structures, become complicated.
That is why light-weight isolated process based concurrency is the best IMHO. Erlang is at the for-front of that. It also has a completely concurrent garbage collector (it won't stop the world) since each process also has a private heap. But as the infomercial guy says, "But wait, that's not all". Add hot code reloading and being able to schedule all these light-weight processes on any number of CPU in an m:n fashion is what takes the cake.
Aha, so is it all rainbows and unicorns. No. You pay for it by getting a sequential slow down. So if you benchmark mandelbrot or matrix multiplication on C++ vs Erlang, C++ will win. Safety and isolation doesn't come for free. So pick and choose based on what requirements you have. There is the syntax issue that people don't like so those are some trade-offs.
None of that explains why you need erlang. Any language can do message passing. The whole point is that we should be expecting these capabilities from every language, rather than pretending using an event loop is in any way reasonable.
You don't. But that is the complete package where isolation and fault tollerance was built in from the start (in the VM, the tool chain, in the libraries) and so on.
Go, Rust, DartVM, Haskell and Scala's Akka all do it. You can do it in C++ and C even. The problem is unless there is true isolation there is always a chance of global data being accessed and updated. There are lock, mutexes, barriers, etc. That is why true isolation comes in.
In a very high concurrency environment with OS based threads it is not always the case. OS threads start to show their overhead ( both in switching and memory consumption ) when we get to 10K+ # of requests (I am assuming some server-client architecture here).
Async or green threads have a smaller overhead of switching, but any CPU based concurrency is usually missing (save for Erlang,Go,Haskell & Rust?). So for small IO bound programs it becomes hard to beat an epoll based loop (as nginx and haproxy show). As soon as any dispatches start computing things then the whole OS process blocks and sockets start throwing errors and everything goes to shit.
Comments
>Performance.
Is identical.
>And the best solution was a solution based on a select/epoll/kpoll loop
But the underlying mechanism does not need to dictate what interface is exposed to be used.
>And it turns out that in most practical application userland threading is actually built on an asynchronous IO select-like call.
That is precisely the point. Presenting it as though the only options are "use native threads" and "use callbacks and event loops" is the myth. Use userland threads, you get the same performance and scalability as an event driven style, as it uses the exact same async calls under the hood, but you get a programming style that is readable and maintainable.
Using an event loop is like rolling your own while loop out of setjmp/longjmp. Yes, the underlying mechanism of a loop is the same, but abstraction is pretty nice.
>For that you need Erlang
Why?
> For that you need Erlang
Because the other side of highly concurrent applications is increase complexity. Both threads and async-based _large_ applications become a mess, fast. No talking about HAProxy type small server, but complicated business rules, state machines and so on. Shared state is hard to reason in non-concurrent application, large concurrent ones, especially with shared data structures, become complicated.
That is why light-weight isolated process based concurrency is the best IMHO. Erlang is at the for-front of that. It also has a completely concurrent garbage collector (it won't stop the world) since each process also has a private heap. But as the infomercial guy says, "But wait, that's not all". Add hot code reloading and being able to schedule all these light-weight processes on any number of CPU in an m:n fashion is what takes the cake.
Aha, so is it all rainbows and unicorns. No. You pay for it by getting a sequential slow down. So if you benchmark mandelbrot or matrix multiplication on C++ vs Erlang, C++ will win. Safety and isolation doesn't come for free. So pick and choose based on what requirements you have. There is the syntax issue that people don't like so those are some trade-offs.
None of that explains why you need erlang. Any language can do message passing. The whole point is that we should be expecting these capabilities from every language, rather than pretending using an event loop is in any way reasonable.
You don't. But that is the complete package where isolation and fault tollerance was built in from the start (in the VM, the tool chain, in the libraries) and so on.
Go, Rust, DartVM, Haskell and Scala's Akka all do it. You can do it in C++ and C even. The problem is unless there is true isolation there is always a chance of global data being accessed and updated. There are lock, mutexes, barriers, etc. That is why true isolation comes in.
> >Performance. Is identical.
In a very high concurrency environment with OS based threads it is not always the case. OS threads start to show their overhead ( both in switching and memory consumption ) when we get to 10K+ # of requests (I am assuming some server-client architecture here).
Async or green threads have a smaller overhead of switching, but any CPU based concurrency is usually missing (save for Erlang,Go,Haskell & Rust?). So for small IO bound programs it becomes hard to beat an epoll based loop (as nginx and haproxy show). As soon as any dispatches start computing things then the whole OS process blocks and sockets start throwing errors and everything goes to shit.
>In a very high concurrency environment with OS based threads it is not always the case.
We're talking about green threads, remember?
>Async or green threads have a smaller overhead of switching, but any CPU based concurrency is usually missing
The point is that async and green threads are the same thing, just one has a better interface. Of course they both have the same downside.
> We're talking about green threads, remember?
Sorry lost context. Yes, for green threads you are right. I had regular (OS) threads in mind.