News for hackers. Stuff that matters.
Re:“Node.js is one of the worst things to happen to the soft... by marssaxman on Tuesday August 23, 2016 @12:40AM (#12341446)
Well.... no, not really. Processors really are fundamentally asynchronous. They are state machines which react when external signals impinge upon them. Synchronous behavior is a useful illusion, a convenient reasoning tool for some kinds of tasks, and our traditional notations for describing computational processes are all based on this model of how computing might be done - but it hasn't actually been done that way since the batch-processing era.

I learned this as I dove into low-level hardware work - drivers and embedded systems. When you're dealing with hardware, life is fundamentally driven by interrupts. Processors spend most of their time asleep. When something happens, the signal level of an input pin changes, and the processor reacts: it wakes up, it starts executing the interrupt handler for that signal, it does things, it sends messages, and then - its job done - it goes back to sleep.

So what, we're talking about normal computers here, you say, surely they're different, right? But no, they really aren't; it's the same process of signal, interrupt, handler, return, all the time. Every context switch, every packet receipt or transmit completion, every timer tick, all of it, it's all driven asynchronously; the system is a hierarchy of event handlers waiting for their opportunity to respond to some external signal.

If you're trying to build an IO system, then, the synchronous model is an expensive illusion. You can force it, but it isn't reality. You spend time waiting, you spend time blocking, you build complex APIs that pretend to poll arrays of connections in parallel; and all you're doing is forcing that illusion of synchrony onto a fundamentally asynchronous world.

It's backwards, all right, but it's backwards because our traditional way of describing computation is backwards, especially the languages which follow the imperative tradition. Functional languages have gained popularity in part because the mental model works better for asynchrony; instead of describing a series of steps to follow, and treating the interrupt as the exception, you describe the processes that should be undertaken in certain circumstances; you effectively construct a state-machine instead of describing a process, and then you leave that state-machine to be poked and prodded by whatever external signals come along to drive it.

Re:“Node.js is one of the worst things to happen to the soft... by tigershark on Tuesday August 23, 2016 @01:40AM (#12341646)
Mainstream processors are synchronous. For this reason there is a global clock needed to synchronise all (most) the chip parts. I remember there was some research on asynchronous CPUs but I don't think it ever yielded anything commercial.

EDIT: Wikipedia link: https://en.m.wikipedia.org/wiki/Asynchronous_circuit

What you are saying is that they react to interrupts asynchronously, but this has nothing to do with the synchronous nature of a CPU. Moreover I think that if you have a CPU that doesn't respect the barriers and reorders the instructions to execute them in parallel, then it's a bugged CPU.

Re:“Node.js is one of the worst things to happen to the soft... by the_duke on Tuesday August 23, 2016 @02:22AM (#12341782)
That's besides the point.

The things that are synchronous within the processor are also synchronous in Javscript.

What is async in JS and Node (unless you use the sync alternatives) is any kind of IO (disk, network). That is also async for the CPU.

And even the things that you would expect to be synchronous inside the CPU are really NOT for modern, out of order CPUs. They do a lot of complicated things to make code run faster, use branch prediction to predict the code path taken and execute (apparently synchronous) instructions in parallel.

Re:“Node.js is one of the worst things to happen to the soft... by notalaser on Tuesday August 23, 2016 @03:56AM (#12342078)
But that only happens when the result is the same as if the instructions were ran synchronously, and synchronization primitives are still needed at the end of these sections.

Even if they weren't, the abstraction layer that you work at with Node is far, far above the point where you care about instruction reordering. If synchronicity is an inherent property of the process that you're implementing (e.g. you want to insert something in the database and then log an event) then no amount of shuffling will alleviate the fact that the logging has to happen after the database insertion.

Edit: the fact that deep down they reorder instructions is a bit scholastic, but if we are to go into these details, it's worth remembering that even the instruction reordering happens synchronously, and that even asynchronous events, like input from an off-chip peripheral, are treated synchronously. The turtles are synchronous all the way :-).

Re:“Node.js is one of the worst things to happen to the soft... by the_duke on Tuesday August 23, 2016 @06:48AM (#12342675)
Haha yeah, sure. Reading the input from an IO device once it's been delivered is synchronous.

But IO is not handled in an synchronous fashion. If CPU cores just waited around idling until a hard drive is done fetching the data (for example), our computers would be very slow indeed.

That was my main point.

Re:“Node.js is one of the worst things to happen to the soft... by notalaser on Tuesday August 23, 2016 @10:40AM (#12344069)
Ah, certainly. In a similar manner, what I meant is that oftentimes it's the process itself that's synchronous, and if the semantics of a language or a toolkit make it difficult to manipulate this sort of flow, people complain.

I've done too little work with Node to have a constructive opinion on it, but I've occasionally had similar complaints about Qt, which I've used a lot more. It uses a signal-slot paradigm where you basically say "when this event is triggered, this function gets called" (in a callback-like, but somewhat more powerful and flexible fashion). It's great for a lot of things, but makes it hard to read and reason about synchronous operations that have to be fit into this form.

Ultimately, though, people cope with it and write working software with it. I imagine it's the same with Node :-).

Re:“Node.js is one of the worst things to happen to the soft... by s_kilk on Tuesday August 23, 2016 @05:26AM (#12342412)
> What is async in JS and Node (unless you use the sync alternatives) is any kind of IO (disk, network). That is also async for the CPU.

The same statement is true of Erlang and Elixir, yet they manage to handle non-blocking async code without either of the daft callback/promise code styles of Javascript.

Even within the confines of async-capable languages, Node is one of the worse options.

Re:“Node.js is one of the worst things to happen to the soft... by the_duke on Tuesday August 23, 2016 @06:42AM (#12342654)
I agree that CSP as in Erlang/Elixir or Go is way better for handling async behaviour.
Re:“Node.js is one of the worst things to happen to the soft... by mateuszf on Tuesday August 23, 2016 @03:19PM (#12346642)
Or clojure, whose flavor compiles down to JS.
Re:“Node.js is one of the worst things to happen to the soft... by tigershark on Tuesday August 23, 2016 @03:42AM (#12342034)
As I said in my previous post, a CPU that doesn't respect barriers and reorders the instructions anyway is a bugged CPU, not a modern one.

If I need the database result before doing anything else then my code is inherently synchronous and it has an hard dependency on the database result. In that context making the DB call asynchronous and waiting for it is more complex than making a synchronous call and proceeding with the normal program flow. The most natural way to write an algorithm is to have everything synchronous and have a "simil-synchronisation" of the asynchronous program flow using an "async monad". And sadly I normally use C# 4.0 that still doesn't have the async construct borrowed from F#, so I'm stuck with tasks and continuations.

Re:“Node.js is one of the worst things to happen to the soft... by talles on Tuesday August 23, 2016 @09:08AM (#12343386)
> And sadly I normally use C# 4.0 that still doesn't have the async construct borrowed from F#, so I'm stuck with tasks and continuations.

Do you know that the async/await constructs are just sugar for the Task class you have access on C# 4.0?

Re:“Node.js is one of the worst things to happen to the soft... by tigershark on Tuesday August 23, 2016 @06:33PM (#12348321)
The C# implementation is a wrap/unwrap of the Task class, in F# it is using computation expressions to lift the synchronous code to an Async monad. The async construct is much easier to reason about, especially with nested tasks.
Re:“Node.js is one of the worst things to happen to the soft... by marssaxman on Tuesday August 23, 2016 @01:49AM (#12341672)
We are talking about different kinds of asynchrony. Yes, the CPU marches to the beat of a single drum, but even that "advance" signal can be seen as an action taken in response to an external stimulus: the voltage change incoming from the clock crystal.
Re:“Node.js is one of the worst things to happen to the soft... by tigershark on Tuesday August 23, 2016 @02:00AM (#12341709)
Nope. When the clock signal is received it means that the components in the critical path have sent the output in the destination, and so the state of the chip is coherent and it starts another step, synchronous across all the chip as the previous. Using your definition then I can say that a block of procedural code that starts on a single thread as soon as an HTTP request is received, processing it and blocking the thread until the end, is asynchronous because it is an action taken in response to an external stimulus, to use your own words. But it is simply not true. The mechanism that dispatches the call to start the subroutine is asynchronous, the code itself is synchronous.
Re:“Node.js is one of the worst things to happen to the soft... by marssaxman on Tuesday August 23, 2016 @02:14AM (#12341748)
I'll take your word for it; we are moving into architecture that sits below my experience now. But we are also below the level of abstraction relevant to the original question, which concerned the design of an API used for communicating with hardware outside the CPU.
Re:“Node.js is one of the worst things to happen to the soft... by Jach on Tuesday August 23, 2016 @02:54AM (#12341877)
Any system that shares a clock is synchronous. Two common communication methods for hardware are SPI, which has a shared clock, and is hence synchronous (https://upload.wikimedia.org/wikipedia/commons/thumb/f/fc/SP...) and UART, which has no shared clock, indeed it can be implemented with a single wire, and is hence asynchronous. Internally the receiver's clock needs to be fast enough to correctly sample data being transmitted to it. (Ed: or I guess you might be able to do something clever with an async circuit fed directly by the signaling line.)

Communicating with hardware outside the CPU doesn't have to be synchronous or asynchronous, it's a design decision depending on what you're trying to accomplish. Languages that don't support both methods are missing half of the design space.

Re:“Node.js is one of the worst things to happen to the soft... by boomlinde on Tuesday August 23, 2016 @07:20AM (#12342787)
I believe it's relevant to point out that most CPUs are synchronous in response to the claim that "Processors really are fundamentally asynchronous."
Re:“Node.js is one of the worst things to happen to the soft... by marssaxman on Tuesday August 23, 2016 @12:45PM (#12345118)
It does seem like I could have phrased that differently, since a number of people have taken it to mean something rather different than I intended.
Re:“Node.js is one of the worst things to happen to the soft... by cookiecaper on Tuesday August 23, 2016 @04:00AM (#12342086)
Isn't this essentially saying that events need a catalyst, there needs to be some external stimulus for something to occur? That's fine. Synchronous programs have that stimulus. It's called "user action". The program, like the CPU, waits until the entity running the show tells it it would like something to happen. Then it does that something in the order specified.

So yes, the CPU waits for the program to ask for some work, just like the program waits for the user to ask for some work. When that work is requested, the program is executed synchronously. I really don't understand how this argument supports the mess that is Node.js.

Re:“Node.js is one of the worst things to happen to the soft... by taneq on Tuesday August 23, 2016 @03:38AM (#12342021)
Well, CPUs do use out-of-order execution to optimise some things: https://en.wikipedia.org/wiki/Out-of-order_execution

But, crucially, they can only do it when it still behaves as if they're operating in-order.

Either way, I agree that CPUs are explicitly synchronous in terms of how they work internally and how they interact with the outside world.

Re:“Node.js is one of the worst things to happen to the soft... by tiagobertolo on Wednesday August 24, 2016 @07:16PM (#12355951)
What really happens is in fact very similar to what happens in the javascript event loop.

The processor processes instructions one after another, synchronously, but whenever he has to use something external he makes the call and continues his normal life until the interruption triggers.

The javascript event loop consists in placing function calls in stack and using WEB api calls asynchronously.

Re:“Node.js is one of the worst things to happen to the soft... by voidr on Tuesday August 23, 2016 @01:49AM (#12341675)
The whole point of abstractions is for us to not have to worry about the underlying complexity. If I want to program in a way that is close to how the hardware works, I'll pick a language like C, however when I choose a high level language, I do not want to care if everything my processor performs is async.

What difference does it make if from the processor's perspective I have:

```js somepoeration().then(function() { // do stuff }); ```

or

```js somepoeration(); // do stuff ```

In both cases my program will just wait for 'somepoeration' to complete before doing anything useful.

Re:“Node.js is one of the worst things to happen to the soft... by bcoates on Tuesday August 23, 2016 @02:29AM (#12341802)
In the second case, IO is not allowed to interrupt between between 'someoperation' and 'stuff' and change your program's state.

In node, the first form is only needed when 'someoperation' has to perform IO to do its job so concurrent operations are unavoidable.

If you're trying to reason about your program, this is huge. It very much matters where these points are. A concurrent thread being allowed to jump in and modify memory at any time at all, even halfway through a primitive math operation (the deranged C / Java / Python[1] memory model) means a correct program is a morass of locks and defensive programming and an obvious program is horribly broken.

Communicating sequential processes (Go, PHP+MySql) makes IO have a modestly simpler synchronous syntax at the cost of communicating between I/O operations much more complex (sending a message to a port or performing some sort of transaction instead of just assigning to a value). It's a tradeoff.

node.js does assume you're writing a network program that needs to overlap multiple communicating I/O operations; if this isn't the case there's no tradeoff to make and non-communicating sequential code is probably easier (think PHP without a database or sessioning)

[1] Python is modestly less braindead by having a very modestly larger set of operations guaranteed to be protected by the GIL. Hoever, it's not composable at all and it doesn't really make reasoning about nontrivial programs easier in practice.

Re:“Node.js is one of the worst things to happen to the soft... by cantagi on Tuesday August 23, 2016 @04:07AM (#12342120)
If you're trying to reason about your program, this is huge. It very much matters where these points are. A concurrent thread being allowed to jump in and modify memory at any time at all, even halfway through a primitive math operation (the deranged C / Java / Python[1] memory model) means a correct program is a morass of locks and defensive programming and an obvious program is horribly broken.

This can be solved by functional programming. Since the original article was written, JS has `const` and `let` [1] . Also, there are now numerous statically typed functional languages that compile/transpile into JS.

Also, if a developer understands exactly how JS is executed, the problem is mitigated:

    var mutableState = {}

    asyncFunc.then(nextAsyncFunc)

    syncFunc()
If you ignore web workers and node.js threading libraries people have written, Javascript always (by design) finishes executing synchronous code before executing any async handlers (your code is in a queue of handlers). This means that syncFunc will never be interrupted by nextAsyncFunc and have mutableState mutated during its execution. Of course, this means that if you do any intense computation synchronously inside a web server, it will block all other requests until it completes, and it will only use one core.
Re:“Node.js is one of the worst things to happen to the soft... by _asummers on Tuesday August 23, 2016 @09:50AM (#12343676)
Const does not mean immutability, only immutable references to the outermost pointer. It is equivalent to final in Java. While that solves the issue with numbers changing state, it does not help objects e.g. For that you need something like immutable.js from Facebook.
Re:“Node.js is one of the worst things to happen to the soft... by majewsky on Tuesday August 23, 2016 @03:32AM (#12341996)
> A concurrent thread being allowed to jump in and modify memory at any time at all, even halfway through a primitive math operation (the deranged C / Java / Python[1] memory model) means a correct program is a morass of locks and defensive programming and an obvious program is horribly broken.

This ignores that most threads, most of the time, operate on their private memory. When your request thread is querying the database and rendering some HTML based on the data from the database, then the only thing that needs to be guarded is the database access. The HTML rendering happens on thread-private data.

Re:“Node.js is one of the worst things to happen to the soft... by fsloth on Tuesday August 23, 2016 @02:24AM (#12341789)
"I do not want to care if everything my processor performs is async."

The point is not the processor. The point is that all IO operations take time. Processing the IO operations concurrently with the serial program logic is where the beef is. Writing asynchoronous code in C or C++ is tedious to say the least in my experience, with weird concurrency bugs looming everywhere.

Re:“Node.js is one of the worst things to happen to the soft... by colordrops on Tuesday August 23, 2016 @02:15AM (#12341752)
That's not accurate. If you have any code after the line in the first example, it will be executed before the function in the "then" call. You could run several asynchronous operations (nearly) simultaneously. I/O will execute as fast as possible rather than wasting cycles running things sequentially.
Re:“Node.js is one of the worst things to happen to the soft... by drawnwren on Tuesday August 23, 2016 @02:32AM (#12341814)
I'm fairly sure his point was that if he wanted code to execute between the calls he would rather write that in his code directly than deal with the cognitive overhead of reasoning about constant async calls.

Async makes a lot of sense in cases where you are waiting for an event outside of your server's process, but async calls in the same code base seem a bit over the top.

Re:“Node.js is one of the worst things to happen to the soft... by posterboy on Wednesday August 24, 2016 @03:21PM (#12354533)
The difference is that an async call takes a callback and the side effects of the callback, if any, are not immediately available.

But anyway the second call may as well be synchronous and blocking.

Re:“Node.js is one of the worst things to happen to the soft... by pjc50 on Tuesday August 23, 2016 @07:00AM (#12342720)
You're right, and you're also being chronically misunderstood. It's not about "asynchronous" in the sense of "unclocked"; it's more about how incredibly fast processors are if and only if they aren't waiting for something else.

The programmer would like to think of the series of operations involved on a per-connection basis. Whereas from the point of view of the processor a "connection" is not a thing; there is only a stream of incoming message fragments at occasional intervals from the network and I/O subsystem. It can request data from persistent storage by what is effectively snail mail: send a message and wait a few million cycles for it to come back.

So the software must consist of a set of state machines. We can push those up into the operating system and call them threads, or down into the user's code and call them callbacks and continuations. Each approach has advantages and disadvantages, and it's important to understand what they are.

(Possibly the language which does this best is Erlang, although it's not as easy to get started with as node.js. Theorists really overlook the vital metric of "time to hello world" in language learning.)

Re:“Node.js is one of the worst things to happen to the soft... by smsm42 on Tuesday August 23, 2016 @07:20PM (#12348561)
> the mental model works better for asynchrony; instead of describing a series of steps to follow, and treating the interrupt as the exception, you describe the processes that should be undertaken in certain circumstances

I could never understand how this works better as a mental model. Say you ask somebody to buy you a gadget in a store they don't know. What do you do tell them:

a) "drive in your car on this street, turn left on Prune street, turn right on Elm street, the store will be after the second light. Go there, find "Gadgets" isle, on the second shelf in the middle there would be a green gadget saying "Magnificent Gadget", buy it and bring it home"

or:

b) when you find yourself at home, go to car. When you find yourself in the car, if you have a gadget, drive home, otherwise if you're on Elm street, drive in direction of Prune Street. If you're in the crossing of Elm street and Prune street, turn to Prune street if you have a gadget but to Elm street if you don't. When you are on Prune street, count the lights. When the light count reaches two, if you're on Prune street, then stop and exit the vehicle. If you're outside the vehicle and on Prune street and have no gadget, locate store and enter it, otherwise enter the vehicle. If you're in the store and have no gadget then start counting shelves, otherwise proceed to checkout. Etc. etc. - I can't even finish it!

I don't see how "steps to follow" is not the most natural mental model for humans to achieve things - we're using it every day! We sometimes do go event-driven - like, if you're driving and somebody calls, you may perform event-driven routine "answer the phone and talk to your wife" or "ignore the call and remember to call back when you arrive", etc. But again, most of these routines will be series of steps, only triggered by an event.

Re:“Node.js is one of the worst things to happen to the soft... by akamaozu on Thursday August 25, 2016 @05:05AM (#12357728)
A list of steps to follow acts way more like the event model than procedural code.

The state of the world can change between steps and the next set of instructions don't apply til you meet some certain criteria or .. event, if you will.

> drive in your car on this street, turn left on Prune street, turn right on Elm street, the store will be after the second light.

Turn left on Prune street doesn't mean nothing else happened between you driving your car and reaching that street.

You could have stopped on the way to pick groceries, changed a tire, bought a snack ... you get the idea.

It doesn't mean you must drive straight to Prune or could get to the destination if you only drove straight there.

Getting to Prune street is an async call. When you reach it, regardless of how, a callback is fired and a new async task is given to you.

Re:“Node.js is one of the worst things to happen to the soft... by smsm42 on Friday August 26, 2016 @03:37AM (#12364822)
It's not "async call", it's a sequence of actions that you perform. Whenever it happens, it's still a sequence of actions. It is a natural way for people to describe a way to do something. The fact that one scenario can be interrupted for another does not change its nature.
Re:“Node.js is one of the worst things to happen to the soft... by ChoHag on Thursday August 25, 2016 @09:35AM (#12358843)
> b) when you find yourself at home, go to car. When you find yourself in the car, if you have a gadget, drive home ...

This is basically exactly how it happens. I say "Can you buy me a thing". The rest is automatically performed by your brain's programming. There is no need to actually mouth the instruction "if you are at home without the gadget, go to your car" because "Can you buy me a thing" automatically links against the code which includes that state processing function.

Re:“Node.js is one of the worst things to happen to the soft... by awjr on Tuesday August 23, 2016 @06:04AM (#12342543)
I think a lot of the issues with JavaScript are around the movement of individuals from synchronous programming languages to the asynchronous JavaScript way.

For some time it resulted in callback hell (http://callbackhell.com/). This was addressed through Promises and more recently Observables, Generators, and async/await.

With transpiling, adoption of these asynchronous concepts has been possible quicker than would have been achieved otherwise.

I would suggest revisiting some of the modern JS constructs to support better use of the underlying cpu architecture.

I will however admit, getting my head around Promises took about a month before it really clicked how powerful this approach can be to support non-blocking IO.

Re:“Node.js is one of the worst things to happen to the soft... by spriggan3 on Tuesday August 23, 2016 @12:07PM (#12344823)
> With transpiling, adoption of these asynchronous concepts has been possible quicker than would have been achieved otherwise.

You're basically admitting that Javascript is not good enough to write asynchronous code and you need to use a third party language that transpiles to Javascript ...

Re:“Node.js is one of the worst things to happen to the soft... by mhink on Tuesday August 23, 2016 @03:02PM (#12346492)
> This was addressed through Promises and more recently Observables, Generators, and async/await.

Parent is talking about ES2015 constructs (or ES2016, in the case of async/await). I don't think anyone will disagree that doing async stuff in ES5 is a massive PITA- but it's a bit disingenuous to claim that the newer Javascript specifications aren't doing enough to fix those problems.

That said, four years ago I would have agreed with you- Coffeescript seemed to be the only game in town making an effort to improve the state of Javascript. But I think the embrace of transpilers in front-end engineering has only helped Javascript thrive, by allowing the community (and core developers) to more easily determine what features will actually make the language better.

(On a completely unrelated note, nice username- DCSS reference?)

Re:“Node.js is one of the worst things to happen to the soft... by OOPMan on Wednesday August 24, 2016 @02:28AM (#12350126)
I've started using async/await and it is something of a game-changer in terms of code readability.

Promises were nice but also subject to nesting and readability problems which the new addition solves nicely.

Re:“Node.js is one of the worst things to happen to the soft... by awjr on Wednesday August 24, 2016 @11:17AM (#12352640)
>You're basically admitting that Javascript is not good enough

Most languages go through iterations and improvements. Transpilers are enabling Javascript to 'fix' issues with the language quickly while being backwards compatible. This is a good thing.

Note by necessity all languages transpile down machine code eventually. ;)

Re:“Node.js is one of the worst things to happen to the soft... by cbHXBY1D on Wednesday August 24, 2016 @12:14PM (#12353078)
I would't say that transpiling and compiling are the same.
Re:“Node.js is one of the worst things to happen to the soft... by OOPMan on Wednesday August 24, 2016 @02:25AM (#12350110)
Try doing some research before you post nonsense. Google isn't more than a click away...
Re:“Node.js is one of the worst things to happen to the soft... by spriggan3 on Wednesday August 24, 2016 @12:03PM (#12352982)
Says the guy who has nothing relevant to say.
Re:“Node.js is one of the worst things to happen to the soft... by dingo_bat on Tuesday August 23, 2016 @11:00PM (#12349383)
That layout made my eyes bleed: http://i.imgur.com/hwKqaUc.jpg
Re:“Node.js is one of the worst things to happen to the soft... by Capt-RogerOver on Tuesday August 23, 2016 @04:34AM (#12342224)
It's not about how the processor works. A developer which is using a language of JavaScript's abstraction level does not think about exactly how a processor works. It's about how a human can easier think up a program and put it into code. And that is mostly synchronous indeed.
Re:“Node.js is one of the worst things to happen to the soft... by marssaxman on Tuesday August 23, 2016 @02:54PM (#12346430)
I find that many misunderstandings of this sort arise from inadequate mental models of the underlying system, and I was trying to present the mental model I use, in which asynchronous IO patterns seem totally natural and normal. Clearly that introduced some unnecessary confusion, so I'll frame things differently next time.
Re:“Node.js is one of the worst things to happen to the soft... by seanp2k2 on Tuesday August 23, 2016 @04:49PM (#12347491)
How many JS-targeted VMs / container things run just one thread of this async-ness when more are available to that container / VM / context? I'd rather run mod_php under preform MPM and take advantage of all the cores. Is there something as easy and well-supported for running Node apps in things like Docker?