Re:The Various Kinds of IO – Blocking, Non-Blocking, Multipl...
by wejick on Monday May 07, 2018 @12:19PM
(#17013955)
Yup basically under the hood I saw golang also using event loop for io, but I never have chance to see the source code to confirm it.
have some write up on this, not directly related tho.
https://wejick.wordpress.com/2017/06/04/tcp-socket-implement...
I also got the sense during the height of the Node craze that some of the people who were very excited about it had the impression that Node had some sort of unique access to a "non-blocking" kernel layer or something (of course, they just weren't thinking about the kernel layer at all) that no other languages were using. In reality, if you set something like a Go program to a single OS thread for execution, you could mechanically translate a Go program into something that executes in principle identically to a Node program at the assembler level, at least in terms of what events come in and what sort of high-level code gets executed in response (vast differences in the literal instruction stream, of course). The converted Go would have a lot more "event handlers" than you'd expect because Go programs also break at function calls and a few other places (as the compiler is doing it it's easy to have lots of "event break points" that you'd never write by hand), but the compiler essentially converts the "blocking code" that uses lots of threads into "non-blocking event-based code". The difference between the two is not at the execution layer; it's at the layer you're programming. In fact pretty much everything nowadays is "non-blocking event-based code" at the execution layer, because the high-powered kernel functions that make that efficient implement event-based code, so anything else you find at a programming-language-level must be converting that abstraction into the language's abstraction. Even using kernel threads still turns into non-blocking event-based code under the hood, if you dig far enough in.
(A more clear example of how critical the layer of abstraction you are looking at is IMHO is the distinction between immutable and mutable. You can implement an immutable abstraction layer on top of mutable storage, which given that our hardware is based on mutable storage, all immutability in programming languages necessarily comes from. You can implement a mutable abstraction on top of an immutable layer with a worst-case penalty of O(log n), as in the worst case you represent memory as a immutable tree of bytes and then mutate as you would normally. Whether or not something is "mutable" or "immutable" critically depends on layer of abstraction you are looking at; it does not have a non-contingent answer, or, if it does, since our hardware is mutable the answer is that immutability does not exist at all. But while true in a sense, that answer is not as useful as one that is contingent on the abstraction layer being examined.)