9 ms·
I have read so many articles which incentivize switching from Node.js to Go and every single one of them (this one included) blabber on about the Node.js event
by cryptica 11y ago
I have read so many articles which incentivize switching from Node.js to Go and every single one of them (this one included) blabber on about the Node.js event loop becoming congested - This is completely misguided - It only shows that the engineer didn't understand the problem.
A single Node.js instance runs its business logic in a single process. A single Go instance can run its business logic in multiple processes. Of course if you're comparing a single instance of Go running on 4 CPU cores, it's going to be faster than a single instance of Node.js running on 1 CPU core.
But the thing the author fails to mention is that there are a lot of Node.js modules which help you easily scale across multiple CPU cores. E.g. PM2 https://www.npmjs.com/package/pm2 https://www.npmjs.com/package/pm2
Had the author of the article actually understood the real cause of the problem, he would have saved himself and his company a lot of time.
Nodejs is still outpacing Golang according to Google Trends and yet I have never seen a single article about switching from X language to Node.js. My guess is that the Go community probably wouldn't exist if it wasn't for this constant form of aggressive propaganda/marketing. Node.js on the other hand doesn't need any marketing/propaganda; it just sells itself.
If you have a scalability problem with Node.js (or any language for that matter) and you can't find a simple solution that doesn't require rewriting your whole app, you're probably not qualified to manage this project at scale - Because scaling across multiple CPU cores is kids' play compared to scaling across multiple machines. Heck, my grandma could scale this thing across multiple CPU cores.
Personally I think Node.js is great because it encourages you to think about these problems sooner rather than later.
- BogusIKnow 11y agoThis is always the problem when you're hype driven. I'm sure the decision to use Node was also hype driven. And they will rewrite again with the new hype, right until they are bankrupt because they didn't invest enough in new features.
- jondubois 11y agoTotally agree! I would say the same thing if someone had a whole app written on Python and were having performance issues (I definitely wouldn't advise them to switch to Node.js or Golang) - If your ecosystem offers the tools to solve the problem, it's better to use these.
- Fluda3 11y agoWhy on earth are both of you getting downvoted so hard? I am so tired of reading hacker news articles with comments that are so pushed down because of subjective opinionated voting that is so obviously skewed towards one personality type. I have so many thoughts and opinions I want to contribute to these discussions but I have zero confidence it will fit within this type of environment that's been created. It really saddens me to see some of the comments that get downvoted here.
- jwdunne 11y agoI agree. My voting policy reflects: I reserve down vote for comments that worsen the quality of discussion. Examples are rude or dismissive comments that fail to address any point in the OPs comment or article. At its worst, I've seen people get down voted for asking beginner level questions. The calibre of folk who post here can, by its nature, make commenting a nervous activity. Getting down voted for trying to expand your knowledge is both harmful and wrong. If I see a comment down voted without the above properties, I up vote to neutralise whether I agree or not. If the comment contributes to debate or discussion, it should be valued. I know I value alternate perspectives.
- skewart 11y agoI completely agree. I do the same thing for subjectively downvoted posts. I want HN to be a place where people share all kinds of ideas and ask questions at any level.
- lucio 11y agohttps://news.ycombinator.com/item?id=11273354 https://news.ycombinator.com/item?id=11273354
- madgar 11y agopg believes downvoting is an appropriate expression of disagreement: https://news.ycombinator.com/item?id=117171 https://news.ycombinator.com/item?id=117171
- dandanisaur 11y ago> he would have saved himself and his company a lot of time she
- deleted 11y ago[deleted]
- jondubois 11y agoWhoops :p
- e12e 11y ago>> Octo was also running across 2 medium EC2 instances which we bumped up to 4. > Of course if you're comparing a single instance of Go running on 4 CPU cores, it's going to be faster than a single instance of Node.js running on 1 CPU core. I'm not intimately familiar with Amazon, so to me it's unclear what "2 medium ec2 instances" mean. It might mean, 2 m3.medium general purpose instances, in which case they actually expose only one cpu core. They also seem a terrible fit for an IO/CPU-bound work load? While I can sympathise with the author that it'd be nice to spend as little as possible on a (micro) service, it strikes me as odd that they first tried going 2x medium -> 4x medium, rather than 2x medium -> 2x x.large (possibly a different intstance type, like c4 -- and run 8 (or whatever) node instances per vm. It does sound like this is a typical area which golang would be a very good fit (Reminds me of: https://talks.golang.org/2013/oscon-dl.slide https://talks.golang.org/2013/oscon-dl.slide ) -- But it also strikes me as odd that rewriting the (apparently) simple service in Go ended up looking cheaper than a) scaling up (rather than horizontally), and b) rewriting the service in nodejs (but with an architecture more suited to the problem).
- TheOtherHobbes 11y agoGo's speed is comparable to Java and nearly as fast as raw C. The only thing faster is raw C++ - and good luck getting a web project finished in a reasonable time using that. Node is not a speed demon. It's not as bad as Python, which can be insanely slow. But if you use Node, your server costs are always going to be some multiple of what they could be. (Also applies to RoR.) Of course the usual argument is that servers are cheap and devs are expensive, so you'll be quicker to market with Node and that's worth the extra cost. Which is fine until you need to run at speed and/or scale. If you start having to pile on the instances, you will be wasting money. If you're big enough to need hundreds of instances, you will be wasting a lot of money. IME it's debatable whether Go can't also be faster for development. There's a learning bump at the start, but I found it easier to write code that just works, easier to write good tests, and easier to deal usefully with errors.
- spriggan3 11y ago> Node.js on the other hand doesn't need any marketing/propaganda; it just sells itself. If Node.js used language X,Y,Z instead of Javascript, it would certainly not have been the success it was. "Javascript on the server" was the marketing/propaganda . Nodejs came at the right moment, Js was exploding, websockets were exploding, coffeescript and co were exploding in popularity. What Go does better than Nodejs is a better standard library, true concurrency, static typing. With Go it doesn't matter if an operation is blocking or non blocking, that fact can totally be abstracted from the client code. Writing callbacks is tedious, promises are tedious, co routines with yield need plumbing and async isn't in the spec. > you're probably not qualified to manage this project at scale - Because scaling across multiple CPU cores is kids' play compared to scaling across multiple machines With Node.js any heavy computation needs to be launched in a separate process, which is not the case with Go. sure you can have one/2/4/8 process dedicated to heavy computation, but it will still be the bottle neck. In the end you'll have to use a different language in order to solve the single threaded problem. Finally there is no mystery as to why some businesses are moving from Node.js to Go: They didn't need anything Node.js provides at first place. They didn't need to use javascript, they didn't need to write "universal" applications with the same logic running in the client and in the server, they didn't need single threaded async programming. Go is not a silver-bullet, but I was a bit sick of having to write a callback every time I wanted to make an http request, just to prototype something.
- Lukasa 11y agoI agree with almost all of your post except this: > With Go it doesn't matter if an operation is blocking or non blocking, that fact can totally be abstracted from the client code. No, it can't, and pretending that it can is misleading in a way that allows large teams of developers to cause themselves real problems. The only sense in which this is true is that you can write a Go function with a simple signature like this: func DoSomeStuff (error) {} And the caller has no idea whether this involves concurrency under the hood (e.g. the function can spawn its own goroutines and channels as it sees fit). But, make no bones about it: this function blocks until it completes. This means that while this function may do concurrent work it is absolutely a blocking function. This is fine: sometimes blocking functions are good. But you cannot write a non-blocking Go function in the same way. To make a function non-blocking you can return a channel out of it for the return value to appear on, like this: func DoSomeStuff (chan error) {} In this model the caller really doesn't have to care whether the function is synchronous or not (though the fact that it was written this way strongly suggests that it is going to return asynchronously, or at least that the developer believes it will have to in the future). Except...that return value just there? That's a Future. It's a terrible, half-implemented version of a Future, but that's exactly what it is. It's a promise to return some kind of result at some point when the underlying process has returned. And if you don't want to block your current goroutine, you cannot block on that channel receive either. That means that you need a callback. There are two patterns for doing that: you could have some kind of central loop that selects over all channels like this and calls the callback functions (boy that looks a lot like Node's event loop, doesn't it!), or you can manually spawn your own callback functions in their own goroutines. Either way, you have callbacks and futures here: you're just building them yourself and calling them something different. There are lots of good reasons to switch to Go: it's a language that makes lots of developers remarkably productive, it has an ingrained philosophy of building concurrent programs, it's pretty damn fast, and it runs on all kinds of awesome platforms. But claiming that Go has learned something magic and new about how to write concurrent software in such a way that you don't have to care whether your code is async or not is just not true: you always have to care.
- awjr 11y agoI'm also finding the amount of open source "solved this problem already for you" solutions available for Node is phenomenal.
- tbrock 11y agoIn my experience, critical problems required by successful language ecosystems that are solved by nodejs modules are either solved poorly or abandoned by the original author. The ones solved by go packages are solved elegantly and maintained. Your mileage may vary but the JS ecosystem is mostly garbage from where I'm standing. Want examples? - Distributed worker queue - Minimal web framework - etc...
- woah 11y agoLeft pad
- mnutt 11y agoI generally agree with the sentiment about scaling across cores and nodes being the same; after all, you're eventually going to need to scale across nodes so you may as well go ahead and get that working. But there are times when it can be a pain. For instance, a node app I run at scale maintains an in-memory read cache that rarely gets updated. When we scale with processes, we end up having to duplicate the cache across every process. We could set up a helper process and have it manage the cache over a socket, or possibly write a c++ module that shares some memory but at that point it's no longer simple and/or there are more parts to potentially fail.
- anton-107 11y agoOr... just use the battle-tested tool that solves this exact problem well for you. Put your cache into Redis or other in-memory cache.
- ptrincr 11y agoYep, redis would solve this. Shareable cache across a distributed cluster of node.js instances.
- regecks 11y agoA network-addressable store such as Redis is not the same as just being able to pull stuff out of memory. A map guarded by an RWMutex is simpler in code, probably more performant for simple access patterns, simpler operationally and effectively can't fail, as the parent points out. Yes, Redis can be the right tool. But, note how quickly we went from "I just want to run on multiple cores" to "I need to share data between my cluster workers so let's install Redis". It's just a total blowup of moving parts. Great-grandparent argument reeks of elitism. I know how to deal with concurrency, parallelism, avoiding data races. Doesn't mean I need to waste my time implementing the primitives every project. To say that the language forcing you into multi-process architecture is a benefit, is a pitifully desperate remark. I wonder what single digit percentage of projects actually go into that territory? Maybe even less than 1%? Maybe with a runtime suitable for the task (e.g. Go or Java or hand-woven C++), less than 0.1%, because you do not run into pointless runtime bottlenecks to begin with? I have implemented such projects, because we needed the workers to be geographically distributed, not because the language runtime fucked us over. This was a decision made in DESIGN not in DEFECT REMEDIATION. I can think of a handful of "single-purposed" reasons to use Node on the server, such as DOM rendering (and other stuff that is only available in Javascript-land). But a serious project, no way. Not sure how people can stomach the inherent lack of safety in the language, the huge (relative to comparable substitutes) number of limitations in the runtime and the ecosystem churn.
- hamburglar 11y ago> Nodejs is still outpacing Golang according to Google Trends and yet I have never seen a single article about switching from X language to Node.js. This is not the endorsement you seem to think it is. > My guess is that the Go community probably wouldn't exist if it wasn't for this constant form of aggressive propaganda/marketing. Node.js on the other hand doesn't need any marketing/propaganda; it just sells itself. Your guess? This is pure emotion arguing here. I have rolled my eyes at the golang converts for literally years and recently I decided to give it a try and it truly sold itself, sans marketing. I also really like node.js, for what that's worth. This comparison sounds like the hurt feelings of the True Believer. Different tools have different applications. Don't ever forget it.
- askyourmother 11y agoOn the plus side, all the devs running to Go from Node, maybe we can finally get all those great libs from npmjs written in go, like Kik, isArray, isThirteen, and so many more classics of robust software engineering that the js community excels at.
- rubber_duck 11y agoDon't forget mature and standardized tools like build, dependency management and distribution
- ldehaan 11y agowhat about just using the built in cluster functionality already in nodejs? I've used it many times with great results and it is really easy to implement.
- ignoramous 11y agoThe clustering module on NodeJs cannot compete with speed that threading, or STM, or Actors offer. The thing with NodeJs is, it is not suited for CPU bound workloads. It's a great fit for I/O bound workloads (where most of the hardwork is done by, say, a DB). Process to process communication has tremendous cost, although shared-memory does make that faster, but at the cost of complicating the interaction. Message-queue (ZeroMQ) based interaction also an option but, by definition, it cannot be as fast as languages that have concurrency support built-in. Reasoning about concurrency is hard, and languages like Go (via CSP), Erlang and Scala (via Actors), Java (via Threads), Rust, and Clojure (via STM) take different approaches to make this less of a pain. CSP and Actors are what seem the most 'natural' of solutions. And that's a major reason why Go and Erlang are frontrunners in the concurrency race.
- pka 11y agoI would say the most natural is STM - you don't need to change much, just wrap your concurrent, shared memory accessing code in a STM transaction, be careful with IO (or use a language which prohibits IO in a STM block like Haskell) and you are done. Actors are pretty nice when it comes to distributed services, and Erlang/OTP is pretty much uncontested here. Threads with manual locking are only useful when speed is really important, but this is somewhat of a moot point when it comes to concurrency. Both STM and Actors perform slower (starvation, message copying overhead). Here [0] is a nice, in-depth discussion about some of the different approaches to concurrency. [0] https://plus.google.com/109566665911385859313/posts/FAmNTExSLtz https://plus.google.com/109566665911385859313/posts/FAmNTExS...
- ignoramous 11y agoInteresting point there. Latency vs Throughput. Using green-threads (Quasar on JVM) might be the best of both worlds then? Akka.io on JVM could pretty much do what Erlang can on BEAM, functionality wise. Although some people have raised concerns over it being a "pseudo" solution and that it is a no match for Erlang.
- KirinDave 11y ago> But the thing the author fails to mention is that there are a lot of Node.js modules which help you easily scale across multiple CPU cores. E.g. PM2 https://www.npmjs.com/package/pm2 https://www.npmjs.com/package/pm2 There are lots of bad things to say about Golang, but it's pretty wrong to suggest that PM2 makes it as easy to write performant systems as Go does. Go even has a really good race detector to help catch the few cases where you can get around channels. The idea that a language cannot directly and transparently support scheduling across CPU cores is an antiquated one. Java is abandoning it. C# abandoned it long ago. Erlang showed long ago that we can do it reliably and with great performance. Heck, even browser-level Javascript is moving away from this idea with async support, although everyone seems rather reluctant to make the plunge towards a stackless architecture. > If you have a scalability problem with Node.js (or any language for that matter) and you can't find a simple solution that doesn't require rewriting your whole app, you're probably not qualified to manage this project at scale I've got 13 years experience, 10 of which are as a distributed systems engineer. I've definitely hit the absolute edges of what off the shelf opensource software can manage, and more than once butted up against bugs and limitations of language runtimes. I'm extremely qualified to say that this is wrong. Sometimes re-architecture and rewriting is the only way forward. That isn't necessarily a failure of the thing to be replaced. It's not even a failure of the architect if it is anticipated and managed correctly.
- jasonwatkinspdx 11y ago> My guess is that the Go community probably wouldn't exist if it wasn't for this constant form of aggressive propaganda/marketing. Node.js on the other hand doesn't need any marketing/propaganda; it just sells itself. This is one of the most absurd and myopic statements I've seen in a while. Go has a vibrant community because many people chose it, for reasons that are entirely valid. Just as people chose Node. You're posting with an enormously superior tone for someone that didn't even read the original post (newsflash: they were using a 4 host service cluster).
- deleted 11y ago[deleted]
- jen20 11y ago"A single Node.js instance runs its business logic in a single process. A single Go instance can run its business logic in multiple processes." Ummm, both of them run in exactly one process, this is how operating systems work. Go can do it's n-m scheduling across multiple _threads_ sure, but threads are not processes (unless as an implementation detail of an OS). If you are running lots of instances of Node, that is a different thing.