5 ms·
Node isn't great when you need not only CPU-efficient but also multithreaded. The multi-threading or even multi-processing story in node is a clusterfuck. Other
by zaarn 7y ago
Node isn't great when you need not only CPU-efficient but also multithreaded. The multi-threading or even multi-processing story in node is a clusterfuck. Other than running two full fat Node.js processes, your options are limited to a few APIs that have more chance to break your kneecaps than run the code.
- halfmatthalfcat 7y agoSure but that's the whole premise of Node, there doesn't _need_ to be multithreading. Whats wrong with spinning up multiple workers (in something like Docker/Swarm/K8S) that split up the work and report back to whatever collector or service that wants the end result? So many problems have spawned out of the desire to thread everywhere that the safety of single-threadedness is a feature not a bug.
- zaarn 7y agoMultithreaded (or Multiprocess) can be done safely. I write a lot of stuff in Rust these days, where (unless you use unsafe) it doesn't even let you do anything that would break under multi-threading, even if you don't use it. As a result, it was incredibly easy to write a light-weight crawler that delivery results into a main worker queue and the data is processed by <cpu_cores> threads. The crawler largely uses async for IO advantages but the worker threads rely heavily on data crunching where your throughput is limited by CPU not by IO and async suffers a bit. And since crawler and worker are on the same process, the latency between a page being grabbed and starting to be processed is incredibly low, any kind of networking would likely cut throughput by a factor of 10 or more. Not even mentioning having to serialize the data instead of relying on references to get read-only copies and only making minimal copies on the stack.
- halfmatthalfcat 7y agoOk, fair point Rust makes multithreading easier but one could easily make the argument that fighting Rust's borrow checker is a huge burden to development. My point is Node isn't as bad as a server-side language as people claim. There are certain use cases where you can leverage Node's strengths and use another language somewhere else where its shines more. I use Node heavily in my backend stack and have been extremely pleased with it's performance and library ecosystem.
- zaarn 7y agoYou can do the things you do in Node, Async, in Rust too. Futures and friends are in nightly and soon in Stable, which enable you to mix the best of both world; Multithreaded and Async. Once you get used to Rust, you fight the borrow checker a lot less.
- hombre_fatal 7y agoYou can level "just use Rust" at any non-Rust ecosystem. It's kind of tired advice. You might as well be recommending Haskell or any other hobby horse language and then argue from a standpoint of technical superiority as if that's the only concern when choosing tools. I use Rust all the time yet I'll still use Node for most HTTP-based applications and tools I start, and not because I'm an idiot or beginner, as many comments here will suggest. They are completely different languages and ecosystems and workflows that satisfy different goals.
- zaarn 7y agoThis isn't "just use rust". This is "just use something more mature". And there are plenty of more mature ecosystems developing Async capability or that have a good Threading story.
- marktangotango 7y agoWhats wrong with spinning up multiple workers (in something like Docker/Swarm/K8S) that split up the work and report back to whatever collector or service that wants the end result? The "spinning up multiple workers" is what's wrong with that. Specifically a language/runtime that does support multi-processing handles it for you; ie gomaxprocs. Another example would be servers like apache forking off several workers during start up (depending on the mpm module). With node this has to be managed manually, as you describe, with Docker or whatever. With a node async server, you're generally not cpu bound, so there's really no reason to try to utilize all the cores on the machine. Except if you are cpu bound, then you'd want to do that.
- HereBeBeasties 7y agoIf you think there's nothing wrong with all the complexity that comes with running a distributed system for something that could be done trivially in a single process in a sensible language, I would like to sell you this hammer - you will find it very useful when you next need to screw something together.
- justinmeiners 7y ago> two full fat Node.js processes Do you know about copy on write?
- zaarn 7y agoStarting up a second Node.js process gives you no CoW advantages, that would occur if you fork off the original node process. But Multiprocess support in Node is piss-poor at best.
- spion 7y agohttps://nodejs.org/dist/latest-v12.x/docs/api/worker_threads.html https://nodejs.org/dist/latest-v12.x/docs/api/worker_threads...
- zaarn 7y agoHave you considered that workers in JS absolutely suck?
- spion 7y agoHave considered you that suck conditions race more with threads and shared memory parallelism? If your counter-suggestion is Rust, have you considered.unwrap() that.unwrap() thinking.unwrap() about.unwrap() managing.unwrap() memory.unwrap() all the time might not be the wisest choice and that a GC is a useful abstraction to have?
- zaarn 7y agounwrap() can very very often be avoided in favor of a simple ? operation, the amount of nesting you suggest does occur... but not in a single function so it's spread over many lines and functions. There are GC libraries for Rust if you need them. Or Python/Lua bindings that have it too. Have you considered that avoiding race conditions isn't hard and you can't avoid having to avoid them even in JS?
- novaleaf 7y agoassuming your code doesn't actually need to be multithreaded, but you want to take advantage of multicore: 1) you can use a launcher like pm2 to auto-fork your node app 2) you can horizontally scale (put your servers behind a load-balancer) if you do need multithreading for computations, you are right that node probably isn't a very good choice, but you have some options: 1) use worker threads 2) offload your intensive computations to a separate process written in a different language.
- zaarn 7y agoEven without multithreading, Rust will soon regain advantages with Async being stabilized. You get the best of both worlds.
- rhinoceraptor 7y agoIt's also a lot harder to write, and in most cases developer time costs a lot more than another instance or two.
- zaarn 7y agoIt's not that much harder to write if you use modern practises and languages.