5 ms·
This is the worst kind of software engineering. There is a massive deadlocking design mistake in the centre of the language - literally a huge red button with
by phoe-krk 7y ago
This is the worst kind of software engineering.
There is a massive deadlocking design mistake in the centre of the language - literally a huge red button with DO NOT PRESS printed on it. Thousands of programmers pass it by every single day, or hour, or minute, and the creators of the runtime insist that it is impossible to fix that button whatsoever; instead, all users need to work around it by ensuring that their code in no way presses that red button on purpose or even by accident.
These people insist that it is impossible to program normally and in a language that is actually sane and does not advertise obvious and gaping design mistakes as "features of the language". These people advertise the analogue of Python's Global Interpreter Lock as the core foundation of their language.
These people advertise Node and the language it implements as practical for implementing multithreaded applications. Posts such as this show what sort of bullshit it is; it is only practical to use Node for parallelism if each single Node instance is only ever run single-threaded. You don't parallelize by running multiple threads, you parallelize by running multiple Node runtimes.
This is no longer an act against productivity or usability. This is simply insane and shows one of the most basic things that are wrong about Node's language and approach. It is impossible to write a multithreaded program if your language of choice makes it trivial, and practically unavoidable, to globally lock your whole runtime with every single line of code you write and import as your dependencies.
- jononor 7y agoThe blog in question indicates some uncommon and questionable engineering practices with Node.js. There are likely hundreds of success stories for every one like that. The first Node.js service I wrote and maintained, processed thousands of requests in parallel and was successfully in production until the company it was developed for ran out of money.
- x86_64Ubuntu 7y agoBut how many of these "questionable" practices get held up as engineering marvels by the creators of the monstrosity? When you look at this blog post, you can see the author really felt a sense of pride in this Frankenstein and wanted to show the whole village.
- tracker1 7y agoI didn't get that impression.. what I got was a few probably common issues that will come up when trying to handle more parallel requests with Node. Note: gRPC doesn't support cluster, so you'd have to manage your own multi-thread (Workers) or multi-process (fork) options.
- JoeAltmaier 7y agoMultithreading is still possible - for clarity of code. Multiple processing threads are running in parallel, but only one at a time. This is a subset of useful applications, but not totally worthless.
- phoe-krk 7y agoYes, it is possible, and actually works - unless one of your threads blocks the event loop and prevents all others from running. This way it takes a single locking thread to halt the whole system, whereas with standard threads a single stalling thread does not cause all others to starve. This is a risk in Node that multiple other runtimes of other languages do not have.
- eshyong 7y agoI mean, running multiple node runtimes (aka multiprocessing) actually sounds like a reasonable compromise for parallelism. That's the standard solution for dynamic languages without great multithreading support. If you needed great multithreading support then Node probably wasn't the right choice for you in the first place, but for most applications, it's probably fine. However, running multiple containers for parallelism sounds a little bit crazy. In the worst case, each container may be running on its own server, but even assuming multiple containers per host, I'm guessing they were running an insignificant number of instances, which is probably why they were able to save $300k in server costs.
- phoe-krk 7y agoYet this is the case mentioned in the article. > We were running 4,000 Node containers (or "workers") for our bank integration service.
- eshyong 7y agoYes, I agree. I'm arguing against your characterization of node as a poor runtime. For many line-of-business applications node is a fine choice. However, plaid has to integrate with many banks which only expose web pages, not APIs, so I'm guessing that they have to do a non-trivial amount of CPU work to scrape and process HTML responses. For this, it may not be such a good choice. All I'm saying is that the choice of language is (usually) not the issue. Poor architecture design causes a lot more problems than whether you choose python/java/ruby/node for your webapp.
- deleted 7y ago[deleted]
- neillyons 7y agoYeah I’m confused why they didn’t start with running multiple processors per container. There must be a reason?
- james-mcelwain 7y agoAre you seriously arguing against event loops as a category? Blocking in non-blocking code is going to be an issue whether the language is C or JavaScript (duh).
- phoe-krk 7y agoFor these kinds of programming, yes, I argue against it. A single stalling function in Node deadlocks the whole system; a single stalling thread in the C++ model still permits other threads to run. This is a risk that is completely avoidable by not using languages which require event loops at their core.
- megous 7y agoJavaScript doesn't require event loop design. You can do a PHP like backend design with JS, where each request is handled by a fresh process, and all JS functions block. There's nothing in the language that prevents this. Some features would become unusable, like Promises and async/await, but those would be worthless in such a design anyway.
- phoe-krk 7y agoNobody does it. Nobody implemented it yet. Nobody made it production ready. That is what a few minutes of googling gave me. As much as I'd like to see it, your JS without an event loop is a purely theoretical construct so far.
- megous 7y agoI did blocking design using Duktape for my runtime Linux distro reinstallation tool and some other projects. It works fine and it's easier than implementing async aware bindings. I wouldn't implement it for the HTTP server/backend use case, because I find the blocking/share nothing architecture of PHP limiting. The point is the language doesn't prevent this kind of architecture.
- winrid 7y agoRunning a Node worker for each thread is standard practice. No different than having a dedicated threadpool for asynchronous programming on the JVM. Yes blocking the event loop is easy. No it's not THAT easy. I've never done it because you think about it while writing code. It's part of the environment. I have had to fix lots of reports etc that try to load up the world and iterate through it in a loop that doesn't yield to the event loop. It's possible to never make that mistake by understanding your environment (just like how managing pointers in C is "hard").
- Osiris 7y ago> Yes blocking the event loop is easy. No it's not THAT easy. I've never done it because you think about it while writing code. To be pedantic, all JavaScript functions block the event loop. It's just that the vast majority of functions execute so quickly that the amount of time your function blocks is very short. I once had a loop that processed tons of data and would block the event loop for 1-3 seconds. I ended up solving it by writing an asynchronous loop which used promises and process.nextTick() to make each iteration a separate execution block on the event loop. But I've only had to do something weird like that once in 10 years of node development.
- winrid 7y agoRight sorry. I meant for a significant amount of time that took down production or caused serious issues. I've taken down prod in other ways though :p At one company I built API middleware that calculated time spent in the event loop vs waiting on dependencies (other apis, Redis, etc) by managing a couple counters per request. It was very helpful.
- MayeulC 7y ago> [javascript] makes it trivial, and practically unavoidable, to globally lock your whole runtime with every single line of code you write and import as your dependencies. As someone not well-versed in js, could you describe one such case? Concurrent access to a global from two threads? Mutexes? My background is more with systems languages and I have done very little js for the browser, so I do not see that big red button.
- phoe-krk 7y agoAn event loop is basically a single thread that executes functions from a FIFO queue. A function can put itself on a queue by "yielding", which means, allowing other functions to execute. If your function blocks, for example, by performing a wait on something without yielding, then nothing else gets computed because of the wait, but the event queue is occupied since the function has not yielded. This breaks the cooperative part of the cooperative multithreading mechanism of Node.
- MayeulC 7y agoAll right, thank you. So it's basically the same as any other non-preemptive multitasking design. If the event loop is part of the Node language/runtime, I can see the case for making it preemptive.
- Izkata 7y ago> So it's basically the same as any other non-preemptive multitasking design. All this has happened before. All this will happen again.
- neillyons 7y agoIn Python, you can execute time.sleep(10_000) in an asyncio program, which means it wont yield back control to the event loop effecting preventing the runtime from doing anything for 10 seconds. In Javascript world I guess you could do the same by replacing time.sleep with some CPU bound code. eg a big calculation or an infinite for loop.