Live data from Hacker News

We've been lied to: JavaScript is fast

jyelewis.com

51–60 of 86 posts

Re: We've been lied to: JavaScript is fast

#51

JavaScript has incredibly good async APIs (promises, async/await, and the seamless integration between the two). As a result, I'm convinced that software written in JS is much more likely to actually perform long-running (IO-bound) tasks in the background/in parallel, simply because it isn't a huge pain to do it. The actual execution speed matters a lot less at that point.

You would think that... But unfortunately this isn't the case. You end up running into the global lock problem where something is stuck deep inside NodeJS and you're at 30% CPU utilization with no idea why. Because everything is async you have no way of understanding what the hell is broken without going into the NodeJS source code and debugging that.

Profiling NodeJS is futile because of its async nature. You end up with a lot of noise and no substance. I'm looking forward to project Loom which would bring Java threads into hybrid green/native mode. That would deliver throughput as fast as NodeJS but with the performance of Java and clarity of simpler stack traces.

Re: We've been lied to: JavaScript is fast

#52
post #13

It was never slow. The event loop is very performant compared to a language with a GIL and a culture of synchronous IO (looking at you, python and ruby), and V8 is amazing. I notice that the author doesn't give any links to claims that JavaScript is slow, and the first two pages of search results are either discussions of how fast JS is or guides to JS performance. Who exactly was lying?

> It was never slow. The event loop is very performant compared to a language with a GIL and a culture of synchronous IO (looking at you, python and ruby), and V8 is amazing.

Having written a lot of code in both Python and JavaScript I disagree here. It's not really the GIL slows down Python compared to JavaScript, that's more down to the lack of a comparable JIT. Yes there's PyPy but it has received a fraction of the investment of V8 and Python is a more complex language to create a good JIT for. Support for multithreading (albeit without parallelism) may be one of a number of factors those complicating factors.

JavaScript doesn't need a GIL because it doesn't support multithreading. WebWorkers are more akin to Python's multiprocessing since objects are not shared between threads.

You have to be careful doing anything compute intensive (e.g. JSON.parse of a large blob of JSON) when using cooperative (async) rather than preemptive (threads) concurrency since you may inadvertently block the event loop, substantially increasing latency for other tasks. Handing off such tasks to a thread pool is harder in JS than Python since you can't easily deferToThread as you can in an async Python program.

Cooperative multitasking has its advantages too of course. An event loop provides a clear boundary for efficiently batching calls which can be awkward with synchronous code. Folks have been writing network servers and in Python using asynchronous techniques for decades now. Twisted is almost 20 years at this point and asyncore was added to the standard library even earlier.

Re: We've been lied to: JavaScript is fast

#53

JavaScript has incredibly good async APIs (promises, async/await, and the seamless integration between the two). As a result, I'm convinced that software written in JS is much more likely to actually perform long-running (IO-bound) tasks in the background/in parallel, simply because it isn't a huge pain to do it. The actual execution speed matters a lot less at that point.

You would think that... But unfortunately this isn't the case. You end up running into the global lock problem where something is stuck deep inside NodeJS and you're at 30% CPU utilization with no idea why. Because everything is async you have no way of understanding what the hell is broken without going into the NodeJS source code and debugging that. Profiling NodeJS is futile because of its async nature. You end up…

I was thinking more about client/interactive software.

For server applications handling many requests in parallel anyways, it's a different story.

Re: We've been lied to: JavaScript is fast

#55

Earlier quoted context omitted.

You would think that... But unfortunately this isn't the case. You end up running into the global lock problem where something is stuck deep inside NodeJS and you're at 30% CPU utilization with no idea why. Because everything is async you have no way of understanding what the hell is broken without going into the NodeJS source code and debugging that. Profiling NodeJS is futile because of its async nature. You end up…

I was thinking more about client/interactive software. For server applications handling many requests in parallel anyways, it's a different story.

Right, async processing performance is hard to predict, but still it helps to be able to use async/await.

This brings to my mind the current logistics crisis in the global trade. Lots of parallel tasks and traffic jams and all of a sudden stores don't have stuff and prices are going up and we don't know when will it be back to normal. That is what Node.js can feel like, because it is hard to understand what tasks execute when and who is waiting for what.

Re: We've been lied to: JavaScript is fast

#56
post #13

It was never slow. The event loop is very performant compared to a language with a GIL and a culture of synchronous IO (looking at you, python and ruby), and V8 is amazing. I notice that the author doesn't give any links to claims that JavaScript is slow, and the first two pages of search results are either discussions of how fast JS is or guides to JS performance. Who exactly was lying?

Never? I clearly remember back in the mid to late 90s, you could easily bring the browser to its knees with a simple JS loop. It wasn’t until Google came around and needed fast JS for Gmail, google docs, maps, etc. that JS became fast as they poured resources into that space and everyone else played catch up.

Re: We've been lied to: JavaScript is fast

#57
post #44

I've never heard anyone tell me that JavaScript is slow. I remember node.js benchmarks in the front page of hn showing it to be as fast as hotspot jvm. And this was pre 2012. And since node is single threaded, you had to run n.cores instances of your app. For the longest time as a kid what I was lied to was that Java was much slower than Ruby/Python and my perception was painted by the startup times.

Java is probably 10 times faster than JS and Pyrhon.

If you say "probably" doesn't that mean it is not really certain if it is that way? May be, may be not. Maybe probably 10 times faster?

Re: We've been lied to: JavaScript is fast

#58

JavaScript is still really slow compared to compiled languages - C, C++, even Java. That super-simple benchmark even after JIT is still 2-3x as slow as the C version, and more complex code can’t be optimized nearly as well. I can confidently say that games and apps in the browser and Electron are noticeably slower than other apps. You don’t see many web games because the graphics required for games today can’t really…

> I can confidently say that games and apps in the browser and Electron are noticeably slower than other apps In my experience the great majority of perceptible slowness in browser apps comes from DOM reflows, not JavaScript

I’ve also seen plenty of web apps which load slowly because they load too much javascript. Most of it unused. I was asked to help out with one project my coworkers were working on where the bundler was pulling in multiple copies of momentjs, each complete with its own copy of the global time zone database. The page loaded way faster once we cleared that out.

A few years ago I noticed most websites just seemed slower than they should on my computer. The culprit turned out to be metamask (an etherium wallet extension). It was adding 700 kilobytes of javascript to each page load thanks to web3. It also exposed my etherium address to any website that asked.

The JS was cached, but just parsing that much code added noticeable lag to every page load. Everything felt zippy once I uninstalled that.

Re: We've been lied to: JavaScript is fast

#59

In the past when I have written basic benchmarking code like the first example, the compiler will typically optimize all the code away. I am curious why this did not happen or what optimization flags were passed in. If it was prevented optimization through flags, is this a fair test?

I've run the C example code through Godbolt with -O2 and... it removed all the loops because the result wasn't used.

Then I added a printf statement and the algorithm came out without too many strangeness.

When I reduce the amount of iterations, the compiler inserts a constant where the calculation would've taken place. The amount of iterations in the benchmark seems to be too high for the compiler to evaluate and optimize out. The clang seems to stop any full evaluation at exactly 101 iterations, meaning there's probably a default limit somewhere puts the limit on a nice, round 100.

I've taken the code, increased the amount of loops by a factor of 10 (to make the differences more pronounced), added a printf/console.log to make sure the loops themselves don't get thrown away (clang does that with -O2) and on my laptop (i7-10750H) the C code, compiled with clang 12, runs 10000000000 iterations in 9.462s whereas the same number of iterations in Node 16 runs in 19.990s. That's more than a 2x execution duration, with more than a 100% speed difference.

For comparison: Java runs in about 9.846s, from the command line (java code.java, no compilation step). C# (dotnet 5) runs in about 9.736s after compilation; compilation takes about a second. Rust runs in about 9.435s after about 0.47s of compilation. Kotlin runs in 9.640s, but it took a few seconds to be compiled into a JAR first. Python 3.9.7 takes forever, but I think that's because its arbitrary length number implementation is trying to make it output the correct result instead of faking it like the other programs are doing. PHP 8 also didn't really stand a chance at over 90 seconds.

JS would probably win in a huge code base consisting of mostly dead code (node_modules, anyone?) where compilation would get in the way of quick edit-run-verify loops, but only starting from scratch without a compiler cache set up. From what I can tell, JS certainly isn't _slow_ like PHP, but it isn't _fast_ either. It's somewhere in between the old interpreters of old and compiled/runtime-JIT'ed languages.

If anything, this algorithm benchmark would indicate that you're probably better off running C#/Java rather than C/Rust because of the negligible performance difference with the huge benefits of language safety with no effort. This benchmark is far from normal program code, of course, so it doesn't really prove anything.

It should be noted that NodeJS outputs the result as "Infinity" whereas C and other languages creates a value that's clearly been bit-wrapped and overflown quite a bit. This can be an advantage (because Infinity + anything = Infinity) or a disadvantage (float math) but that's just how the language works.

Edit: looking at the rest of the code, I've also benchmarked the loop vs functional approach (Node 16, same device).

    // Generate numbers
    numbers = [];
    for (let i = -10000000; i  x > 0).sort((a,b) =>a-b)[0];
    console.log(lowest);
^ this runs in 1.007s

    numbers = [];
    for (let i = -10000000; i  0 && i 
^ this runs in about 0.629s

I wouldn't call a near 40% speed difference "only 2ns". The functional approach is very comfortable to program in, but it comes at a real cost and should definitely be avoided complex in algorithms.

Java handles streams very poorly. However, LINQ is quite fast:

    var numbers = new long[20000000];
    for (var i = -10000000L; i  x > 0).OrderBy(i => i).First()
    );
^ this runs in 0.346 seconds.

That doesn't make it quite optimal, though:

    var numbers = new long[20000000];
    for (var i = -10000000L; i  0 && i 
^ This runs in 0.151s

These examples aren't very conclusive either. Rust's loop version runs in 0.100s and a shitty iterator version that collects the entire iterator and sorts it runs in 0.130ms. Again, the real fight here seems to be between C# and something closer to the metal.

Re: We've been lied to: JavaScript is fast

#60

The second code comparison is supposed to point out that the second version. Unfortunately, still not easy enough to read to avoid bugs caused by javascript's "unique" approach. `findSmallestPositiveValue([2,11])` gives the wrong value for the supposedly better function. > Even if the second function takes twice as long as the first, we are in the realm of nanoseconds. How can you possibly know this? You can make eit…

> websites that have noticeably slow javascript "startup" times.

Doesn't that just mean it can take a long time for the browser-application to download all of its scripts?

That can certainly take a long time but it depends on 1) The speed of the web-server(s) serving those scripts 2) The speed of the network you are connected to

So web-sites taking a long time to execute their JavaScript on your PC in the browser does not say much about the speed of JavaScript the language.

But it is a practical concern of course. Which brings to my mind the fact that JavaScript programs can exhibit extreme parallelism, because they can execute in millions of browsers at the same time, think SETI-search, or unauthorized crypto-mining.

So in practice JavaScript can have a huge computational throughput, in other words great speed, because it can execute on multiple clients at the same time, easily.

Post reply on HN