What's new

Welcome to yeywe | Welcome My Forum

Join us now to get access to all our features. Once registered and logged in, you will be able to create topics, post replies to existing threads, give reputation to your fellow members, get your own private messenger, and so, so much more. It's also quick and totally free, so what are you waiting for?

Five Myths used in “Golang vs Node.js” debate

Hoca

Administrator
Staff member
Joined
Mar 19, 2024
Messages
549
Reaction score
0
Points
16
Recently, I’ve read quite a bit of comparisons of Node.js with Golang. Unfortunately, Google search on this subject is dominated by, ahem, not so informed opinions – with lots of outright ridiculous claims; and while repeating ridiculous claim over and over doesn’t make it less ridiculous – it certainly can form a completely wrong opinion among developers, and even worse – among decision-makers. To help dealing with it, I made a collection of the most popular/most ridiculous myths about Node and Golang – to bust them here.

Myth #1: Node.js is single-threaded, so it doesn’t scale​


BB_emotion_0012b.png
Probably the most popular deadly wrong point touted by competitors of Node.js is that, as [Sathananthan]1 proudly writes, “Node.js is single-threaded, which means that the execution instructions are performed in sequence.”.

Truth #1: If programmer does nothing to exploit multi-coring in her program, both golang and Node.js are single-threaded. However, if programmer does want to go multicore, she has to use goroutines (in Golang) , or cluster module (in Node). All one might want to argue that golang’s approach is better – however, this is at least arguable (more on it in Myth #3 and Myth #4 below).


1 an article which got #1 placement and Google “feature snippet” on “Node.js vs golang” search, is an article by an undisputed authority in the field a guy writing his 3rd-semester project. Bravo, Google!</sarcasm>



Myth #2: Node.js is interpreted​


Numerous sources discuss allegedly interpreted nature of JavaScript; see, for example, [Harkushko]: “But since JavaScript is an interpreted language, it takes more time to execute code written in Node.js than it does to execute code written in Go.”

Truth #2: While performance of Node.js is indeed usually lower than that of Go, it has nothing to do with the language being interpreted (JavaScript as a specification doesn’t need to be interpreted or compiled; it is particular implementation which is interpreted or compiled, and Node.js v8 engine does have a JIT compiler). This is corroborated by an observation that performance difference between the two is relatively small (see Myth #5 below).

Myth #3: Goroutines is The way to scale​


BB_emotion_0025b.png
It is very often mentioned that Golang is designed for scalability; just as one example, the very same ultra-high-rated-by-Google [Sathananthan] says “Golang was really designed for scalability and concurrency, without too much hassle.”. This usually comes along with some wording about goroutines-based concurrency, at least implying that scalability can/should be achieved with goroutines.

Truth #3: In fact, goroutines have a potential Really Big Problem(tm) when it comes to scalability – as goroutines DO allow accessing non-const global variables, this not only opens the whole can of worms reliability-wise (heck, mutex-based stuff is inherently untestable!2), but also limits scalability to one single box (moreover, Shared-Memory systems DO suck scalability-wise even on single box; this has lots of reasons ranging from Amdahl’s law to unnecessary cache invalidations due to mutex-induced thread context switches). Granted, current golang practices DO encourage channel-based Shared-Nothing concurrency – which indeed DOES scale, but to the best of my knowledge, (a) it is NOT enforceable in Go, and (b) golang run-time (unlike, say, Erlang/OTP runtime) doesn’t support/detect “pure” nonconst-global-access-free goroutines (which could be moved even to another box if necessary). BTW, Node.js is Shared-Nothing by design – enforcing the only scalable model out there (and also saving us from LOTS of next-to-impossible-to-find bugs as a side benefit).


2 and Go’s runtime race detection provides only a palliative care to this Big Fat Problem(tm)



Myth #4: Concurrency in Golang is easy​


BB_emotion_0009b.png
[Cheney] says “Go’s headline feature is our simple, lightweight concurrency model. As a product, our language almost sells itself on this on feature alone.”.

Truth #4: Golang or not, concurrency (leave alone efficient concurrency) is never easy. To illustrate it, let’s take a look at an excellent article [Deleplace] on an optimization experience with Golang. Long story short – first, supposedly “good”3 Golang code was made 2.5x faster by removing fine-grain concurrency and making the whole thing sequential(!!). Then, when adding a coarse-grain concurrency, wall-clock time did improve further, but number of goroutines going into 120K proved to be too much for Go runtime (causing 12 cores to perform merely 1.5x better than single-core version – that’s about 8x inefficiency CPU-wise, energy-wise, and CO2-footprint-wise)4, so final implementation (the most efficient one, gaining whopping 23x improvement over original “good” code) was based on 12 workers. But hey – not only this kind concurrency optimization struggle is very similar regardless of the programming language, in addition I cannot help not to mention that 12-workers for 12-cores would be the way we’d scale our Node.js implementation in the first place! In other words –

efficient concurrent implementations happen to be strikingly similar in Golang and Node.js

There is no magic out there – and while costs of goroutines are somewhat lower than that of threads, common techniques such as going coarse-grain and limiting the number of outstanding tasks are still necessary.


3 at least some Golang developer wasn’t shy to put it to the Github as an explicit example of a “good” code
4 effectively busting yet another myth of Golang being ok with millions of goroutines



Myth #5: Golang performance is similar to that of C/C++​


[Sathananthan] says that Golang has “Similar performance characteristics as with C or C++”.

Truth #5: if we take a look at IMO-the-best-inter-language-benchmark-results-available ([Debian1][Debian2]), we’ll see that Go lost all 10 benchmarks to GCC C, losing from 20% to 5x (with a median around 2.5x). Moreover, if speaking about performance of Node.js ([Debian3]), it happens to be between 20% faster and 5.9x slower than Golang (with a median of 1.4x). In other words,

Performance-wise, Golang is closer to Node.js than to C/C++

Bottom Line​


BB_emotion_0006b.png
Myth busting aside, I do NOT feel that either Node.js or Golang is “better” per se; in a sense, they’re strikingly similar (especially if speaking about Go with channels instead of mutexes), so all the attempts to push one of them as an “inherently better” one are pretty much pointless. The only field where Golang has a realistic edge, is that 1.4x performance advantage, but this is going to change with an advent of Node.cpp, which will enable C++-like performance for those-Nodes-which-need-it.




References​



[Sathananthan] Sabesan Sathananthan, “Want to be a best Web Developer? Learn Golang not Node.js”

[Harkushko] Liliia Harkushko, https://yalantis.com/blog/golang-vs-nodejs-comparison/

[Concurrency made easy] Dave Cheney, https://dave.cheney.net/paste/concurrency-made-easy.pdf

[Deleplace] Val Deleplace, “Go code refactoring : the 23x performance hunt”

[Debian1] “Go versus C++ g++ fastest programs”

[Debian2] “C gcc versus C++ g++ fastest programs”

[Debian3] “Node js versus C++ g++ fastest programs”


Acknowledgement​


Cartoons by Sergey GordeevIRL from Gordeev Animation Graphics, Prague.

P.S.​


Don't like this post? Criticize↯

P.P.S.​


We've tried to optimize our feed for viewing in your RSS viewer. However, our pages are quite complicated, so if you see any glitches when viewing this page in your RSS viewer, please refer to our original page.
 
Top Bottom