4 ms·
> The JavaScript context is running an event loop which most likely must perform locking on its message queue and callbacks to async operations are queued for e
by deno 14y ago
> The JavaScript context is running an event loop which most likely must perform locking on its message queue and callbacks to async operations are queued for execution on a future tick of this event loop. All of this seems very preemptive to me.
There’s a single loop which blocks until the task yields while waiting on the result from one of the worker threads. That’s cooperation. All queued connections are starved until that happens. In Erlang, or just with pthreads, the connections are processed independently. Think separate event loops for each connection.
> To me, cooperation is when you yield the thread to another coroutine. This saves the state of the call stack, the registers, everything; meaning you don't force your user to keep that state in closures. The user code in a cooperative environment feels sequential and blocking and results are passed by return values, not by calling continuations.
That has noting to do with how execution is scheduled. Cooperative scheduling requires passing continuations[1], so the execution can be resumed while it waits. The simplest implementation is to use callbacks, the way node.js does it. Futures and deferreds[2] are a little bit more sophisticated (Python’s Twisted, probably something for node.js exists as well), as they allow for better composition. And of course you can hide the continuations entirely, which can be done in both Scala (compiler plugin) and Python (gevent or using generators), rewriting the direct control flow by breaking it on yield points automatically (this is how exception throws work in most languages btw), but the limitations inherent in having a single event loop per thread will still exist.
[1] https://en.wikipedia.org/wiki/Continuation-passing_style https://en.wikipedia.org/wiki/Continuation-passing_style
[2] https://en.wikipedia.org/wiki/Futures_and_promises https://en.wikipedia.org/wiki/Futures_and_promises
- ricardobeat 14y ago> a single loop which blocks until the task yields while waiting on the result from one of the worker threads Yes, node.js is cooperative, yet since all I/O is asynchronous the time spent blocking is mostly dispatching and simple operations, it doesn't block while waiting - that's where it's performance and high concurrency comes from. Doing CPU-heavy work in the server/main process is a no-no.
- deno 14y agoObviously that approach is fine enough for many things. Before node.js, people have written those kinds of servers in Twisted or Netty, with great results. Netty based framework powers, for example, much of Twitter. I was just explaining how the scheduling works :)