News for hackers. Stuff that matters.
Re:“Node.js is one of the worst things to happen to the soft... by Jemaclus on Monday August 22, 2016 @11:55PM (#12341281)
Disclaimer: I worked with Node.js full-time for about 14 months, ending about 9 months ago. I'm willing to admit that the following complaints may or may not be out of date, especially with ES6 and newer Node versions. Proceed with grains of salt at the ready.

There are a lot of things to like about Node.js, but the primary thing that bothers me about it is the obsession with async. It's a language/framework designed to make pretty much everything async.

In the real world, almost everything is synchronous, and only occasionally do you really want async behavior. By that I mean, you almost always want A, B, C, D, E, F, G in that order, and only occasionally would you say that you want async(H,I). But with Node, it's the other way around. You assume things are async, and then specify synchronous behavior.

Instead of assuming A; B; C; D; E; F; G;, you wind up with a ton of code like A.then(B).then(C).then(D).then(E).then(F).then(G);

...I know that's a contrived example, and I know you don't really need to do it that way, but so many people do, and it really illustrates the point. In Node.js, you are explicitly synchronous / implicitly async. Most other coding paradigms (including Go) better match what I consider reality, which is that everything is implicitly synchronous, and you specify async behavior when you need it.

Basically, I think it's backward. But perhaps like the OP, I just can't wrap my head around it.

The NPM stuff... well, I think all ecosystems have their pros and cons. I'm not a huge fan of NPM, but it does the job for the most part, and I'm curious as to how people would actually improve it, rather than just complain about it all the time. I don't really have any good ideas (knowing nothing about how package management actually works under the hood).

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?
Re:“Node.js is one of the worst things to happen to the soft... by athenot on Tuesday August 23, 2016 @12:23AM (#12341381)
> In the real world, almost everything is synchronous, and only occasionally do you really want async behavior.

From an Ops perspective, I disagree. At a systems level, everything already is async, whether you like it or not. So then the options are either to embrace the admittedly hectic nature of async, or pretent that things are synchronous and impose those constraints to maintain a logical purity from a programmer's standpoint.

For example, in a synchronous setup, it's perfectly logical to service an incoming http request with a few database queries followed by some more logic and some more DB queries or API calls; wrap all the result and send it back. The same in node.js forces the code author to think about those initial DB queries (which may run simultaneously), about how to roll up the result when they are all done and pass it to callbacks.

But while thinking about those callback interactions, there's a motivation to reduce the number of steps, or to factor them out into their own module or microservice. This promotes thinking at a systems level instead of just at the level of "1 request serviced by 1 handler". Perhaps that big request can be broken up into several API calls and the web page can load those asynchronously. Perhaps the smaller microservices end up building up less memory usage per request (or spread it out in a way that makes clustering more efficient).

One may see async as a hurdle in the way of logical abstraction, or as a way to align thinking with the realities of network programming.

Re:“Node.js is one of the worst things to happen to the soft... by enraged_camel on Tuesday August 23, 2016 @02:07AM (#12341736)
>>So then the options are either to embrace the admittedly hectic nature of async, or pretent that things are synchronous and impose those constraints to maintain a logical purity from a programmer's standpoint.

Logical purity is important. It helps people reason about their code better, which in turn makes them more productive.

The reason we have frameworks and high-level languages is so that we can take advantage of abstractions and not worry about the underlying complexities of the system. If a framework is making you "embrace the hectic nature" of those complexities, why use that framework in the first place? Might as well use a language like C, which actually is a low-level language designed for developing hyper-optimized software. Node.js, on the other hand, is supposed to be a Web (read: high-level) framework. That's why implicit-async doesn't fit its nature, and in large codebases you see nested callbacks all the way down.

Re:“Node.js is one of the worst things to happen to the soft... by dahauns on Wednesday August 24, 2016 @06:13AM (#12350913)
Ever heard of the Law of Leaky Abstractions?

Logical purity is completely useless if the chosen abstraction leaks like the Titanic after the iceberg.

And no, the alternative is not "just use C", but choosing an abstraction that better fits the nature of the underlying system.

Re:“Node.js is one of the worst things to happen to the soft... by knucklesandwich on Tuesday August 23, 2016 @02:07AM (#12341734)
The advantage you're describing is concurrency, which doesn't necessarily require an asynchronous/event-driven programming model. Synchronous concurrency is built around threads to achieve concurrent execution (i.e. instead of waiting on events for several requests to finish in parallel, you fork off a thread for each to process each request synchronously).

Node came of age about a decade after epoll was introduced, when not having access to nonblocking IO was considered a big liability for a couple of dominant web programming languages, and they built their concurrency model around the semantics of epoll.

However, there are languages like Haskell, Erlang, and Go that IMO did the right thing by building a synchronous programming model for concurrency and offering preemptable lightweight processes to avoid the overhead associated with OS thread per connection concurrency models. These languages offer concurrent semantics to programmers, yet still are able to use nonblocking IO underneath the covers by parking processes waiting on I/O events. It's not the right tradeoff for every language, particularly I think lower level languages like Rust are better off not inheriting all the extra baggage of a runtime like this, but for higher level languages I think its probably the most convenient model to programmers.

Re:“Node.js is one of the worst things to happen to the soft... by ohyes on Tuesday August 23, 2016 @12:56AM (#12341495)
I think what this really gets at is that callbacks are a shitty concurrency primitive.

They certainly make sense from an implementation perspective (I've got this interpreter and I want to do concurrency... I know, I'll just use it to trampoline callbacks).

But callbacks are too low level to reason about easily to some extent, it's kind of like writing everything as a series of goto statements. Sure you can do it, but good luck following it.

The advantages of asynchronous execution are lost. This isn't limited to nodejs, I've experienced similar problems with Python twisted...

Channels (such as in clojure/core.async) or lightweight processes and messaging (such as in erlang/beam), are much more enjoyable to work with.

This shouldn't really be a shock, however, they're higher level abstractions based on real computer science research by people who really thought about the problem.

Re:“Node.js is one of the worst things to happen to the soft... by int_19h on Tuesday August 23, 2016 @01:27AM (#12341597)
Callbacks are ugly when you have to deal with them directly. But a little bit of syntactic sugar to capture the current continuation as a callback - such as C# await, or the now-repurposed yield in Python - makes it very easy and straightforward to write callback-based async code.
Re:“Node.js is one of the worst things to happen to the soft... by davidjnelson on Tuesday August 23, 2016 @02:54AM (#12341875)
Babel and regenerator let you use await in es/js too.
Re:“Node.js is one of the worst things to happen to the soft... by flamedoge on Tuesday August 23, 2016 @02:56AM (#12341881)
Python does have await from asyncio
Re:“Node.js is one of the worst things to happen to the soft... by int_19h on Wednesday August 24, 2016 @03:59PM (#12354769)
Apparently, I wasn't paying as much attention to the state of async in Python 3.5 as I should have. Looks like they actually have the most featureful implementation of that right now, complete with async for all constructs where it can be sensibly implemented and provide some benefits (like for-loops and with-blocks).
Re:“Node.js is one of the worst things to happen to the soft... by jackweirdy on Tuesday August 23, 2016 @05:19AM (#12342379)
Fortunately JavaScript is a flexible enough language that you don't only have to use the primitives it provides.

Promises (which were pure JS before they were ever added to the language) are a more-composable structure for reasoning about concurrency. I don't think I've put more than one line of callback-style code into production per month.

Re:“Node.js is one of the worst things to happen to the soft... by Klathmon on Tuesday August 23, 2016 @05:40AM (#12342460)
And async/await are such a game changer its amazing.

I finally bit the bullet and tried it even though it's still not final syntax, it simplified most of my code while keeping the execution exactly the same.

It really is a night and day difference.

Re:“Node.js is one of the worst things to happen to the soft... by azernik on Tuesday August 23, 2016 @01:13AM (#12341553)
On the subject of nice higher-level concurrency abstractions, I'm very taken with the current fad for Promises/Futures (a la ES6 or Scala), which are basically a translation of the Haskell IO monad to plain English.
Re:“Node.js is one of the worst things to happen to the soft... by gclaramunt on Tuesday August 23, 2016 @02:17PM (#12346046)
Isn't closer to the Async monad?
Re:“Node.js is one of the worst things to happen to the soft... by hacknat on Tuesday August 23, 2016 @10:32AM (#12344000)
I was a node developer back when it hadn't been packaged yet (yes, I'm a hipster). I left a few years ago for many reasons, including the fact that I think the community sucks.

I agree with everything you say, and I want to add to it. People compare node to things like Go, PHP, Python, etc, which is a mistake. As someone who had to write a fairly complex native module for node that a lot of people still use (5000 downloads this month, according to npm), nodeJS is a framework not a language.

Node is not in control of the underlying code that implements the ES spec. Node is a bunch of C/C++ middleware wrapping V8 and implementing various server and process utilities. That is all it is.

Why is this important? Because it biases the community towards piling on feature after feature and moving at an insane pace, sometimes in ways that are outside of the community's control. Node is biased against stability, because they feel the need to keep up with V8. Counter this with Go, which has been frozen as a language for 8 releases now, with each release fine tuning the stability of the compiler/language, runtime, and libs.

That native module that I mentioned earlier, I have a bunch of open requests to make it work with nodeJS 6 (no idea what this is), which is the fourth breaking V8 interface change I've had to deal with. The native module clocks in at >2000 lines of C++. I implemented the same library in Go and it clocks in at 500 lines. I've only had to modify the Go version of this library once, and it was to take advantage of a new feature (i.e. I didn't have to update it).

Node's continual quest for features is going to keep it in the niche web development space it has come to dominate. There is simply no way I would architect a system with such an unstable platform.

Re:“Node.js is one of the worst things to happen to the soft... by Illniyar on Tuesday August 23, 2016 @01:25AM (#12341586)
Doing synchronious is much clearer and easier, most of the async patterns (like yield/await and promises) really just try to simulate a sync paradigm.

But there is one great reason why node's async first mentality is superior- when you want to do async in node, you don't have to worry that some library you are using is going to lock up your thread.

In any other language, you have to painstaikingly make sure everything you use isn't doing sync, or try and monkeypatch all io operations (python has something like that).

Frankly, for me, when I'm dealing with webservers I find myself needing to use async quite a lot.

Re:“Node.js is one of the worst things to happen to the soft... by icebraining on Tuesday August 23, 2016 @02:27AM (#12341795)
In any other language

No; for example, in Go, every time the code does IO, the scheduler will re-assign another goroutine, and they asynchronously get back to the other when the IO finishes. It doesn't need any special support by the library.

Re:“Node.js is one of the worst things to happen to the soft... by Illniyar on Tuesday August 23, 2016 @03:25AM (#12341974)
That sounds like an implicit async/await, which sounds rather awesome.

I haven't really gotten around to trying Go yet, but there are definitely great things going on there.

Re:“Node.js is one of the worst things to happen to the soft... by zigzigzag on Tuesday August 23, 2016 @05:45AM (#12342477)
It's just green threading, which has been around for a long time.

You can run millions of threads on a single machine with modern Linux kernels if you either have lots of memory or simply minimize your stack sizes and usage. The kernel doesn't care much. You don't really need any special language features. The main reason fibers/green threads/goroutines/etc have become popular lately is that common language runtimes and standard libraries don't resize thread stacks on the fly and tend to like very deep call stacks, so minimising your memory usage can be rather hard.

Re:“Node.js is one of the worst things to happen to the soft... by soulbadguy on Tuesday August 23, 2016 @11:06AM (#12344307)
> he main reason fibers/green threads/goroutines/etc have become popular lately is that common language runtimes and standard libraries don't resize thread stacks on the fly and tend to like very deep call stacks, so minimising your memory usage can be rather hard.

Green-thread, coroutine have been around for a long time, the recent popular is probably due to increase prevalence of people trying to solve the C10K problem.

Green thread, are more efficient both in term of memory consumption and context switching than kernel thread (even more so with compiler support).

The linux kernel might be able to handle millions of threads, but thruth is one can do it much more efficiently in userland

Re:“Node.js is one of the worst things to happen to the soft... by Mister_Snuggles on Tuesday August 23, 2016 @01:05PM (#12345286)
> Doing synchronious is much clearer and easier, most of the async patterns (like yield/await and promises) really just try to simulate a sync paradigm.

I'm currently working on some lighting (DMX-based theatre lighting) software and the ability to have my 'effects' written in a sequential manner by using 'yield' is actually incredible. It's simplified my code a huge amount and made it a lot easier to reason about.

There is a function called every frame, which then calls each effect. Since each effect is a Python generator function, it can be written sequentially and just has to yield whenever the frame is computed.

Re:“Node.js is one of the worst things to happen to the soft... by epidemian on Tuesday August 23, 2016 @02:28AM (#12341800)
> when you want to do async in node, you don't have to worry that some library you are using is going to lock up your thread.

> In any other language, you have to painstaikingly make sure everything you use isn't doing sync

I haven't found that to be the case TBH. In most other languages i've used i don't have to worry about foo() being syncronous or not. I can assume that. In other words, after the control returns from the foo() call, i can assume that what foo() is supposed to do has been completed. In the case that foo() needs to do some IO operation, i can usually rely on it doing a syscall that will block the thread and put it to sleep, instead of doing something nefarious like busy waiting.

And that's it. The current thread will sleep while the IO operation in foo() completes, and the OS (or VM if we're talking green threads) will switch the CPU to do something else in the main time. And if it's a web server we're talking about, that something else may be another web server thread, serving a different request. Yay, preemptive multitasking!

In the case of node, you do very much have to worry about a function call being synchronous or asynchronous, as it defines the way it has to be called. In the former case, it can be called "normally":

  let a = foo()
  // use `a`
In the async case, some code gymnastics need to be involved:

  // Either callbacks:
  foo(a => { 
    // use `a`
  })
  // Or promises:
  foo().then(a => {
    // use `a`
  })
  // Or promises + await syntax:
  let a = await foo()
It may not seem a big problem at first, especially if using the `await` syntax is an option. But to me the biggest problem of this technique is that the "async-ness" of a function cannot be abstracted away. If a function `foo` that has always been synchronous, and that is used in several places, needs to be changed, and this change implies `foo` calling an async function `bar`, then `foo` will need to become async too, and all the places where `foo` is called will need to be changed. Even though this internal `bar` async call was an implementation detail of `foo` that shouldn't have concerned `foo` callers. And this propagates all the way up: if any of the places where `foo` was called was, in turn, a synchronous function too, then that function will also need to be refactored into an async one, and so on and so forth.

And that's basically why i find node's distinction between sync and async functions so frustrating :(

PS: Cooperative multitasking does not imply this weird syntax complexity of having two different kinds of function calls that cannot be freely intermixed. For instance, Eralng "processes" use cooperative multitasking, but the "yields" are managed implicitly by the VM, so you don't need to explicitly yield control of the current thread to let other stuff run concurrently.

Re:“Node.js is one of the worst things to happen to the soft... by savanaly on Tuesday August 23, 2016 @01:14AM (#12341554)
Maybe it's because I learned to write code in javascript (browser and node) -- does that make me an async native? -- that I feel the reverse of you. Synchronous just doesn't feel right, and I'm happy with the way node is assumes async. I'm one of those who finds the new Await syntax sort of unsettling at a gut level.
Re:“Node.js is one of the worst things to happen to the soft... by formula1 on Tuesday August 23, 2016 @12:19AM (#12341369)
Async isnt about ordered operations its about waiting. When you make a database call, you thread can sit there for 50 ms or do something useful. You can outsource rendering work to a child process. You dont have to let infinite loops block events.
Re:“Node.js is one of the worst things to happen to the soft... by flukus on Tuesday August 23, 2016 @02:31AM (#12341809)
That 50ms isn't necessarily wasted. When I get the results of that database call I want the results returned to the user ASAP, with async operations the thread may be too busy to do that.

We do this daily in real life. It's more efficient for me to have 10 minutes down time at work while I'm waiting for someone else than it is for me to start something else then either get interrupted or finish another task before I respond to the person I'm waiting on.

Re:“Node.js is one of the worst things to happen to the soft... by vincnetas on Tuesday August 23, 2016 @03:52AM (#12342061)
It depends on how fast you can switch context. If you can switch context in 1ms, then waiting 50ms is a waste of 48ms. But if context switch takes 100ms then sure, it's better to wait idling.
Re:“Node.js is one of the worst things to happen to the soft... by echelon on Tuesday August 23, 2016 @12:46AM (#12341459)
This seems absurd to me. What exactly are we going to sit there and do while waiting on the data we need to fulfill a query?

I work on services where any given endpoint may handle many thousands of requests per second. We don't care about a slight penalty to query the database, because these are very short, and our services return responses on the order of 100 ms.

Maybe these are things you care about in a language like Javascript, but in something statically typed, they just don't seem like a problem.

Re:“Node.js is one of the worst things to happen to the soft... by WatchDog on Tuesday August 23, 2016 @01:23AM (#12341581)
> What exactly are we going to sit there and do while waiting on the data we need to fulfill a query?

Fulfil more/other queries.

> ...in something statically typed, they just don't seem like a problem.

What has static typing got to do with asynchronous IO?

Re:“Node.js is one of the worst things to happen to the soft... by mplewis on Tuesday August 23, 2016 @01:12AM (#12341548)
You could use the same thread and process to do something else instead of having to spin up another thread or process.

If you're running a web server, you can handle another request, then come back to the first one when the data arrives.

Re:“Node.js is one of the worst things to happen to the soft... by jtrtoo on Tuesday August 23, 2016 @03:06AM (#12341917)
So shouldn't the only question ever be:

* Would we rather burn computing resources (i.e. on new threads) or calendar time+human resources (i.e. on code refactoring)?

Followed closely by:

* And does it even matter for our situation? (i.e. since for many situations getting every last drop of performance out of a system isn't the real obstacle; it's making it do something useful for the end-user or business)

Re:“Node.js is one of the worst things to happen to the soft... by cookiecaper on Tuesday August 23, 2016 @04:05AM (#12342113)
and let's not kid ourselves that anyone trying to get maximum performance out of anything would be running JavaScript. If you need max performance, you write C, and sometimes raw ASM.
Re:“Node.js is one of the worst things to happen to the soft... by akamaozu on Thursday August 25, 2016 @05:14AM (#12357756)
That's like saying if you aren't driving a Veyron you obviously don't care about speed so use a moped.
Re:“Node.js is one of the worst things to happen to the soft... by formula1 on Tuesday August 23, 2016 @06:36AM (#12342638)
Having a successful async paradime helps closer to bare metal by setting a standard for how things should work. Now you can likely find more asynchronous libraries that attempt to copy the functionality of something familiar than creating something completely fresh
Re:“Node.js is one of the worst things to happen to the soft... by mahyarm on Tuesday August 23, 2016 @01:11AM (#12341545)
In a client world, you definitely care about using all of your resources and never halting the rendering/main thread. There is often many things going on at once and you usually need to keep main thread halts under 16ms
Re:“Node.js is one of the worst things to happen to the soft... by jackweirdy on Tuesday August 23, 2016 @05:22AM (#12342394)
> What exactly are we going to sit there and do while waiting on the data we need to fulfill a query?

On the data you need to fulfil one client's query. The answer is that you do stuff you need to fulfil other clients queries, until you're ready to come back to the first one.

I don't see what type systems have to do with your comment either. Scala uses asynchronous concurrency primitives (Futures) and it's statically typed.

Re:“Node.js is one of the worst things to happen to the soft... by greenleafjacob on Tuesday August 23, 2016 @10:29PM (#12349266)
It's common in high performance code to use spin locks (also called busy waiting) to reduce latency. In some circumstances it's better to do nothing and be available almost immediately to do some work than to naively context switch away and pay the penalty of context switching back later. Check out how futexes are implemented in Linux for an example - hybrid mutex and spin lock.
Re:“Node.js is one of the worst things to happen to the soft... by Salgat on Wednesday August 24, 2016 @03:54PM (#12354746)
If you're running a web server, you're processing possibly hundreds of requests at any given time. Especially since JS is single-threaded, you want to minimize blocking by awaiting, aka yielding your thread to another thread to let it continue processing its own request. Async minimizes time spent doing nothing.
Re:“Node.js is one of the worst things to happen to the soft... by catnaroek on Tuesday August 23, 2016 @04:02AM (#12342098)
> make pretty much everything async.

This isn't intrinsically bad. It just makes Node.js biased towards use cases that benefit from asynchronous I/O, which is a perfectly valid design choice. Sensible programmers already know that computationally intensive tasks that benefit from actual parallelism are best served by a different tool.

What's absolutely horrible about Node.js is how they make everything asynchronous: explicit continuation passing everywhere. In other words, the user is responsible for manually multiplexing multiple logical threads through a single-OS-threaded event loop. If it sounds low level, it's because it is low-level. A high-level programming language ought to to better than this.

Other languages get this right: Erlang, Go, Clojure, Scala, Haskell, Rust, etc.

Re:“Node.js is one of the worst things to happen to the soft... by bitwize on Tuesday August 23, 2016 @01:48AM (#12341667)
1) All data has a type.

2) All I/O (if you're doing it right) is asynchronous.

Node does things the right way around; it's just a shame that Linux (unlike Windows) doesn't have async I/O baked into the heart of the OS and well supported with useful kernel primitives.

Synchronous I/O by default means you're wasting your CPU cores. When running at Web scale, you ALWAYS want to leverage async I/O in order to not have the CPU idle blocking on some I/O operation, and you don't necessarily want the synchronization and memory overhead of multiple threads. That's why Node is designed the way it is.

By using the 'co' library and generators you can write async code almost as if it were sync. It works like the inline-callbacks feature of Twisted.

Re:“Node.js is one of the worst things to happen to the soft... by icebraining on Tuesday August 23, 2016 @02:16AM (#12341754)
Synchronous I/O by default means you're wasting your CPU cores.

But that's the thing: synchronous code doesn't mean synchronous execution. The language/platform should be able to make it async for you, without forcing you to re-shape your code. And it's not a rare system: even plain old threads work like that - in fact, they're often a good solution: https://www.mailinator.com/tymaPaulMultithreaded.pdf

Re:“Node.js is one of the worst things to happen to the soft... by dahauns on Tuesday August 23, 2016 @08:52AM (#12343279)
The code itself is not the problem. Data, specifically mutable state and dependencies are. Relying on the platform to figure those out for efficient async execution hasn't worked out so well in the past...
Re:“Node.js is one of the worst things to happen to the soft... by bjourne on Tuesday August 23, 2016 @03:03AM (#12341909)
> it's just a shame that Linux (unlike Windows) doesn't have async I/O baked into the heart of the OS and well supported with useful kernel primitives.

What about epoll()?

> Synchronous I/O by default means you're wasting your CPU cores.

You can implement synchronous IO on top of an async backend using the above mentioned epoll. I believe that is how read() and similar syscalls are implemented. They block the programs thread, but the core is free to run other threads while it waits for IO.

Re:“Node.js is one of the worst things to happen to the soft... by bitwize on Tuesday August 23, 2016 @10:07AM (#12343818)
epoll doesn't change the fact that all of the well-supported I/O primitives under Linux are synchronous. Not necessarily blocking, but synchronous. There are aio_* system calls in the kernel but they suck. There are only a few, and the kernel devs seem to think that doing sync I/O in a different process/thread is good enough so they may not even last forever in the kernel.

Linux does not support I/O completion ports, or even a completion-based model for I/O at all. (Instead it uses the readiness model, requiring you to waste cpu cycles in a polling loop checking if an fd is "ready", that is if you don't want to spin off a new process.) In Linux you can't check an I/O buffer for data and schedule the call that would fill the buffer if it's empty in one system call, the way you can in Windows.

Windows was modelled after VMS, which was designed for reliability and throughput. Linux was modelled after Unix, which was designed so that Ken Thompson could play games on a scrapped PDP-7.

Re:“Node.js is one of the worst things to happen to the soft... by Gracana on Tuesday August 23, 2016 @11:35AM (#12344552)
This sounds like something straight out of the Unix Hater's Handbook. :)

But epoll is not the fault of Unix. Linux gets it wrong, but others do not. There's a good (and wildly entertaining) discussion/rant about it in this BSD Now episode: https://www.youtube.com/watch?v=l6XQUciI-Sc

Re:“Node.js is one of the worst things to happen to the soft... by bitwize on Tuesday August 23, 2016 @03:12PM (#12346587)
epoll (and kqueue) are products of Unix's approach to I/O, which is synchronous by design. You can build synchronous I/O routines out of asynchronous primitives, but not the reverse (without resorting to separate processes/tasks/threads).

epoll is more wrong and broken than kqueue, but neither are up to the level of capability the NT kernel offers.

Re:“Node.js is one of the worst things to happen to the soft... by 15155 on Tuesday August 23, 2016 @04:17PM (#12347191)
> requiring you to waste cpu cycles in a polling loop checking if an fd is "ready",

epoll in edge-triggered mode does not require this loop to exist in userland. In edge-triggered epoll (or the similar kqueue construct), your work thread(s) will be asleep until the kernel chooses to wake one up.

Re:“Node.js is one of the worst things to happen to the soft... by jcrites on Tuesday August 23, 2016 @02:57AM (#12341886)
> Synchronous I/O by default means you're wasting your CPU cores

When a process becomes blocked (like due to synchronously waiting for IO to complete), the kernel will context switch away to another runnable process. The process that becomes blocked essentially goes to sleep, and then "wakes up" and becomes runnable again once the operation completes. The CPU is free during this time to run other processes.

If you need to do multiple different of these things concurrently, then you can run multiple processes. Writing a single process with async code won't make that process faster. To do more things at the same time you can run multiple processes. Context switching between different processes is what the kernel scheduler is designed to do, and it does so very efficiently. There isn't much overhead per thread. If I recall correctly, Linux kernel stacks per thread are 8 kilobytes (with efforts under way to reduce that further [4] - also discussed in [1]), and the user stack space is something the application can control and tune. The memory use per thread needn't be much.

Using all available cores to perform useful work is the most important thing to achieve in high-throughput code, and both async and sync can achieve it. Async doesn't become necessary for high performance unless you're considering very high performance which is beyond the reach of NodeJS anyway [2]. Asynchronous techniques win on top performance benchmarks, but typical multithreaded blocking synchronous Java can still handily beat async NodeJS, since Java will use all available CPU cores while Node's performance is blocked on one (unless you use special limited techniques). There's some good discussion about this in the article and thread about "Zero-cost futures in Rust" [1]. The article includes a benchmark which compares Java, Go, and NodeJS performance. These benchmarks suggest that the other tested platforms provide 10-20x better throughput than Node (they're also asynchronous, so this benchmark isn't about sync/async).

Folks might also be interested in the TechEmpower web framework benchmark [2]. The top Java entry ("rapidoid") is #2 on the benchmark and achieves 99.9% of the performance of the #1 entry (ulib in C++). These frameworks both achieve about 6.9 million requests per second. The top Java Netty server (widely deployed async/NIO server) is about 50% of that, while the Java Jetty server, which is regular synchronous socket code, clocks in at 10% of the best or 710,000 R/s. NodeJS manages 320,000 R/s which is 4.6% of the best. In other words, performance-focused async Java achieves 20x, regular asynchronous Java achieves 10x, and boring old synchronous Jetty is still 2x better than NodeJS throughput. NodeJS does a pretty good job given that it's interpreted while Java is compiled, though Lua with an Nginx frontend can manage about 4x more.

I agree that asynchronous execution can provide an advantage, but it's not the only factor to consider while evaluating performance. If throughput is someone's goal, then NodeJS is not the best platform due to its concurrency and interpreter handicap. If you value performance then you'll chose another platform that offers magnitude better requests-per-second throughput, such as C++, Java, Rust, or Go according to [1] and [2]. Asynchronous execution also does not necessarily require asynchronous programming. Other languages have good or better async support -- for example, see C#'s `await` keyword. [3] explores async in JavaScript, await in C#, as well as Go, and makes the case that Go handles async most elegantly of those options. Java has Quasar, which allows you to write regular code that runs as fibers [5]. The code is completely normal blocking code, but the Quasar runtime handles running it asynchronously with high concurrency and M:N threading. Plus these fibers can interoperate with regular threads. Pretty gnarly stuff (but requires bytecode tampering). If async is your preference over Quasar's sync, then Akka might be up your alley instead [6].

> By using the 'co' library and generators you can write async code almost as if it were sync.

For an interesting and humorous take on the difficulties of NodeJS's approach to async, and where that breaks down in the author's opinion, see "What color is your function?" [3].

[1] https://news.ycombinator.com/item?id=12268988

[2] https://www.techempower.com/benchmarks/#section=data-r11&hw=...

[3] http://journal.stuffwithstuff.com/2015/02/01/what-color-is-y...

[4] https://lwn.net/Articles/692208/

[5] http://docs.paralleluniverse.co/quasar/ [6] http://akka.io/

Re:“Node.js is one of the worst things to happen to the soft... by zigzigzag on Tuesday August 23, 2016 @06:37AM (#12342641)
Node isn't interpreted, it runs on V8 which is a fairly advanced JIT compiling VM.

The main reason Node is so slow is that, as you point out, it doesn't do threading at all, and JavaScript is just inherently difficult to optimise into machine code, even though V8 makes a good effort.

Re:“Node.js is one of the worst things to happen to the soft... by Yaggo on Wednesday August 24, 2016 @02:48AM (#12350207)
The benchmark code uses multiple processes to utilize all CPU cores (standard way in Node.js land).

I would blame the highly dynamic nature of the language for (relative) slowness – the price you pay for flexibility / quickly-writable code. That being said, it's still fast for dynamically typed language.

Re:“Node.js is one of the worst things to happen to the soft... by marcosdumay on Tuesday August 23, 2016 @12:35PM (#12345037)
What do you think a VM is?

It does not target your hardware architecture. Just because your code is in binary instead of text, it does not become less of an interpreter.

Re:“Node.js is one of the worst things to happen to the soft... by Jtsummers on Tuesday August 23, 2016 @12:47PM (#12345138)
https://developers.google.com/v8/design

C-f for "Dynamic Machine Code Generation"

V8 compiles it to native machine code for execution. It's not an interpreter or a VM with its own bytecode.

Re:“Node.js is one of the worst things to happen to the soft... by marcosdumay on Tuesday August 23, 2016 @01:21PM (#12345442)
Cool. There is no VM, just a runtime not much different from the ones from other compiled languages. It compiles your code piece by piece, and optimizes during that compilation.

This is a very interesting solution for JavaScript, but I think it's constrained by the language and could become better if it were fully compiled.

Re:“Node.js is one of the worst things to happen to the soft... by Jtsummers on Tuesday August 23, 2016 @02:41PM (#12346298)
Perhaps for the use-case of node, being fully compiled could be a bit better. But I'm not convinced. Java has demonstrated (over two decades now) that initial compilation to machine code isn't essential for performant software (ok, less than two decades for hotspot JITs in Java). The cost for node is in startup time, but this is, like with Java, amortized over the life of the program. For a single-run executable, it's perhaps too costly (but we use truly interpreted languages for this as well, so depends on the task), but for a server, it's potentially pretty good.
Re:“Node.js is one of the worst things to happen to the soft... by marcosdumay on Tuesday August 23, 2016 @04:17PM (#12347197)
Yes, that was for the specific case of Node. For web use, full compilation is a clear loss.

Java can make great use of JIT exactly because it's interpreted. When you make partial compilations, you lose a lot of JIT opportunities, and a lot of static optimization opportunities too. Yet, it looks like V8 attenuated this somehow, and got good performance anyway. Must have been a feat.

Re:“Node.js is one of the worst things to happen to the soft... by lmm on Tuesday August 23, 2016 @05:18AM (#12342373)
> 2) All I/O (if you're doing it right) is asynchronous.

Not true. Synchronous I/O is higher-throughput. If you need to do a large amount of high-latency I/O (e.g. web requests) then asynchronous can end up being lower-overhead overall, but making everything async is just as bad as making everything sync.

Re:“Node.js is one of the worst things to happen to the soft... by regularfry on Tuesday August 23, 2016 @02:01AM (#12341712)
NPM would be hugely improved if:

1) `npm install` on two different machines at the same point in time was guaranteed to install the same set of dependency versions.

1b) shrinkwrap was standard.

2) it was faster.

3) you could run a private repo off a static file server.

Re:“Node.js is one of the worst things to happen to the soft... by jdlshore on Tuesday August 23, 2016 @07:01PM (#12348464)
Check in your modules.
Re:“Node.js is one of the worst things to happen to the soft... by metafunctor on Tuesday August 23, 2016 @02:19AM (#12341759)
In the past, I was involved with building a Scheme interpreter which was automatically asynchronous, without need for manually handling it with callbacks.

Basically, it was lightweight threads which would yield execution to other threads whenever waiting for I/O, or explicitly yielding. It allowed for a very straightforward linear programming style, no callback hell.

Coupled with a functional programming style, there was rarely a need for mutexes or other synchronization between threads.

When a thread yielded, the current continuation was captured and resumed when the thread was ready to continue. At the bottom of it all was a simple event loop where the Scheme interpreter dispatched I/O and timeouts. Scheme happens to have support for continuations built in to the language, so the implementation was actually quite simple.

Re:“Node.js is one of the worst things to happen to the soft... by ambrop7 on Tuesday August 23, 2016 @03:30AM (#12341991)
I've built something similar but a completely new programming language with backtracking as the major feature. The intended use is dynamic OS configuration especially network interface configuration.

The interpreter is single-threaded but there is simple concurrency between the "processes", that is a process yields when it has nothing more to immediately do.

Old online demo build through Emscripten (it misses many new features such as functions): https://rawgit.com/ambrop72/badvpn-googlecode-export/wiki/em...

Docs currently still dying on Google Code archive: https://code.google.com/archive/p/badvpn/wikis/NCD.wiki

Source: https://github.com/ambrop72/badvpn

Re:“Node.js is one of the worst things to happen to the soft... by umanwizard on Wednesday August 24, 2016 @03:42AM (#12350409)
> Basically, it was lightweight threads which would yield execution to other threads whenever waiting for I/O, or explicitly yielding. It allowed for a very straightforward linear programming style, no callback hell.

How is this different from a normal multithreaded C program on a POSIX kernel?

When I call read(), my thread is suspended until the data comes back, and another thread can run.

Re:“Node.js is one of the worst things to happen to the soft... by lacker on Tuesday August 23, 2016 @12:23AM (#12341380)
If you think promise-based code with a lot of "then" is annoying, perhaps ES7 async/await will make you happier.
Re:“Node.js is one of the worst things to happen to the soft... by nurettin on Tuesday August 23, 2016 @01:16AM (#12341559)
This is exactly what I was about to write. Also, the amount of "callbacks, that's how it's supposed to be" and "hardware is like that" and "programming is hard, deal with it" kind of replies for a readily solved problem are staggering.
Re:“Node.js is one of the worst things to happen to the soft... by lootsauce on Tuesday August 23, 2016 @01:43AM (#12341656)
I don't know about others but the imposition of try catch for error handling in async/await seems to cut against the syntax gains over promises.
Re:“Node.js is one of the worst things to happen to the soft... by nurettin on Tuesday August 23, 2016 @04:04AM (#12342110)
If by promises you mean the `some.fun(had).catch(had, function(){handle stuff here})` syntax compared to async/await, that is actually a very fair point and it does make two syntaxes similarly verbose.

However, it is still easier to follow a ladder of conditional statements using async/await compared to escher-style stairs of callbacks inside callbacks.

Re:“Node.js is one of the worst things to happen to the soft... by edwinjm on Tuesday August 23, 2016 @07:03AM (#12342728)
Interesting. In which language is this "readily solved"?
Re:“Node.js is one of the worst things to happen to the soft... by iends on Tuesday August 23, 2016 @07:33AM (#12342836)
Erlang, Elixir, & Go have nicer models.
Re:“Node.js is one of the worst things to happen to the soft... by nurettin on Wednesday August 24, 2016 @01:21AM (#12349847)
Re:“Node.js is one of the worst things to happen to the soft... by Capt-RogerOver on Tuesday August 23, 2016 @04:49AM (#12342268)
It's a solution for a made-up problem. Sure, async/await makes it easier. But not as good as the normal sync code would be. And for what reason? The concurrency problems are already a solved issue in many many frameworks. Sure, if you do fully manual threads in something like C++ and code up everything yourself - you're in for the trouble down the road unless you are a good professional. But there are heaps of concurrency frameworks in all major languages that make this very easy. And what about performance, how does JavaScript justify putting virtually every single return value of every function into some Promise object? Talk about wasted resources.
Re:“Node.js is one of the worst things to happen to the soft... by Salgat on Wednesday August 24, 2016 @03:56PM (#12354755)
Await lets you preserve the sequential syntax that normal programmers are used to. It's syntactic sugar, which is fine if you prefer to code in a way that most people are familiar with, versus callbacks that can be messier (callback hell).
Re:“Node.js is one of the worst things to happen to the soft... by edwinjm on Tuesday August 23, 2016 @07:06AM (#12342745)
JavaScript uses one thread so not switching threads with all its contexts saves a lot of overhead.
Re:“Node.js is one of the worst things to happen to the soft... by Capt-RogerOver on Tuesday August 23, 2016 @06:56PM (#12348434)
JavaScript being single-threaded is one of it's biggest drawbacks. This is universally agreed on by both it's proponents and critics. Yes sure, some very few resources are wasted on each thread, but in case of JavaScript, it wastes a lot more by not using all the cores, of which there are usually several present in almost any modern computer that will run JS.
Re:“Node.js is one of the worst things to happen to the soft... by jroseattle on Tuesday August 23, 2016 @02:53AM (#12341872)
> The NPM stuff... well, I think all ecosystems have their pros and cons. I'm not a huge fan of NPM, but it does the job for the most part, and I'm curious as to how people would actually improve it, rather than just complain about it all the time. I don't really have any good ideas (knowing nothing about how package management actually works under the hood).

  - Remove the Couchbase dependency
  - Make login authentication a plugin or API-based
  - Integration with Github/Gitlab for automated publishes
to name a few.
Re:“Node.js is one of the worst things to happen to the soft... by amelius on Tuesday August 23, 2016 @03:26AM (#12341977)
Yes, and on top of that, it is asynchronicity without real concurrency. Imagine one part of the code doing a long CPU-bound computation; the rest has to wait!

It's like the worst of two worlds.

Re:“Node.js is one of the worst things to happen to the soft... by adrianratnapala on Tuesday August 23, 2016 @01:50AM (#12341676)
With due caution about @marssaxman's point that software is fundemantally interrupt driven, I will agree with this.

I work an a real-time system that is controlled by RPC from a desktop. We claim we want to keep the real-time code small and simple.

Yet I find people pushing complexity down onto the RT system even when the real-time guarantees aren't needed because the PC code responds to it using a callback driven async model. It's easier to put a non-real time for loop into the RT thread than to emulate a for loop on the PC.

Re:“Node.js is one of the worst things to happen to the soft... by zaidf on Tuesday August 23, 2016 @12:02AM (#12341310)
I think the idea of having a powerful scripting language based on JS is a godsend in many ways. But like you, I also feel that async is a bad default for a language that has such widespread use.

I love being able to use one syntax to write 95% of my code(instead of having to switch between JS / python / php etc.) but some of NodeJS's programming and ecosystem realities are annoying to say the least.

Re:“Node.js is one of the worst things to happen to the soft... by sesm on Tuesday August 23, 2016 @05:39AM (#12342453)
Everything is async in node, because doing sync operations in event loop is terribly slow.
Re:“Node.js is one of the worst things to happen to the soft... by zigzigzag on Tuesday August 23, 2016 @05:51AM (#12342500)
No. That's nonsense. Everything is async in node because node is based on the V8 Javascript engine which is not thread safe. V8 is not thread safe because it was designed for web browsers, and browser rendering engines are also not thread safe.

People have tried to retcon node's choices as being based on some sort of deep technical justification, but that's not the case: its limits are the limits of the material it's made of, not a specific design choice.

If you look at more advanced VMs like the CLR or JVM then they support all modes of operation: synchronous/blocking (which is often what you want), synchronous/blocking with many threads, async with callbacks, async with continuations ... node only supports one. How is that better?

Re:“Node.js is one of the worst things to happen to the soft... by edwinjm on Tuesday August 23, 2016 @07:12AM (#12342760)
JavaScript was explicitly designed to use one thread and prevent all kinds of concurrency problems. It requires getting used to, but it's very powerful.

Look at this page and tell me the JVM is better: https://docs.oracle.com/javase/7/docs/api/java/util/concurre...

Re:“Node.js is one of the worst things to happen to the soft... by zigzigzag on Tuesday August 23, 2016 @08:11AM (#12343027)
Javascript was never explicitly designed to use one thread: it used one thread because Netscape used one thread. This is back in the 1990s when multicore on the desktop didn't exist and JS execution speed was a non issue.

The page you linked to shows a full and complete library of concurrency tools, which you don't have to use if you don't want to. How is this evidence of being worse?

Re:“Node.js is one of the worst things to happen to the soft... by dahauns on Tuesday August 23, 2016 @10:54AM (#12344186)
Sure, powerful. As long as you're mainly I/O-bound and shared-nothing.

Oh, and your link actually DOES show that the JVM is better. It can give you everything node.js has and then some.

If you want to see something like node.js for grown-ups, take a look at Vert.x or Akka (& Frameworks based on it), for example.

(Sorry for the snark, it's been a long day...)

Re:“Node.js is one of the worst things to happen to the soft... by Deinumite on Tuesday August 23, 2016 @11:53AM (#12344705)
That library is probably one of (if not the most) powerful concurrency libraries in existence.
Re:“Node.js is one of the worst things to happen to the soft... by jupp0r on Tuesday August 23, 2016 @03:17AM (#12341940)
The universe is inherently concurrent. It only makes sense for programming languages (which are used to model problems in this universe) to follow along.
Re:“Node.js is one of the worst things to happen to the soft... by jomamaxx on Tuesday August 23, 2016 @12:14AM (#12341349)
Your comments about the annoyingness of async are real.

BUT

Just because you want to do ABCDE does not mean it's feasible.

You can access a file, read it, compute something, depending on that access another file, read it, write something via Http Post somewhere else.

BUT the nature of i/o is such that the problem is 'intrinsic' - it's not a 'node.js' problem so much.

Of course you know that you can do everything syncrhonously if you want, but then you get hangups and what not waiting for underlying resources, networking calls etc..

The nature of a distributed system is inherently async, and so we have to live with it.

That said - maybe you have some examples of where async definitely should not be used?

The other huge problem with Node.js is the vast, crazy expansion of tiny libraries, supported by ghosts, that change all the time. A simple lib can depend on a dozen others, with varying versions, everything changes almost daily. A small change somewhere can really jam things up.

This is by far my #1 concern, although it can kind of be avoided if you're careful.

Re:“Node.js is one of the worst things to happen to the soft... by marcosdumay on Tuesday August 23, 2016 @12:40PM (#12345073)
> Just because you want to do ABCDE does not mean it's feasible.

Every single language is able to do ABCDE, except for JavaScript. Yes, I guess that means it's impossible.

> The nature of a distributed system is inherently async, and so we have to live with it.

The nature of a distributed system is the one you impose onto it by design. Computer systems are not something that appear at nature and we just harvest.

There are plenty of synchronous architectures for distributed systems, from distributed logical clock ones, for clock domain ones. People tend to avoid async ones anyway.