remix logo

Hacker Remix

Skeptical of rewriting JavaScript tools in "faster" languages

163 points by todsacerdoti 3 days ago | 313 comments

munificent 2 days ago

> I don’t think that JavaScript is inherently slow

It is.

Brilliant engineers have spent decades making it faster than you might expect, subject to many caveats, and after the JIT has had plenty of time to warm up, and if you're careful to write your code in such a way that it doesn't fall off the JITs optimization paths, etc.

Meanwhile, any typical statically typed language with a rudimentary ahead of time compiler will generally be faster than a JS VM will ever approach. And you don't have to wait for the JIT to warm up.

There are a lot of good things about dynamically typed languages, but if you're writing a large program that must startup quickly and where performance is critical, I think the right answer is a sound typed language.

__s 2 days ago

I spent years tuning a JS game engine to play nice with JIT for best performance. Then rewrote engine in Rust/WASM over a few weekends (turns out JIT friendly code is straightforward to port to statically typed language) & things are an order of magnitude faster now with the benefits of static type checking & no spooky jit perf to optimize for

Just because JS can be fast doesn't mean it's a pleasure to write fast JS

causal 2 days ago

It mostly depends on the application. If you're doing complex transforms over hundreds of GBs of data- yeah, use a workhorse for that.

But the vast majority of slow JS I've encountered was slow because of an insane dependency tree or wildly inefficient call stacks. Faster languages cannot fix polynomial or above complexity issues.

munificent 21 hours ago

> If you're doing complex transforms over hundreds of GBs of data-

It's not always about giant datasets. Latency matters too for software that is run frequently by users.

I maintain a code formatter. In a typical invocation, it's processing only a few hundred kilobytes of input data. But it is invoked every time a user hits control-S, thousands of times a day. If I make it a few hundred milliseconds slower, it materially impacts their flow and productivity.

> Faster languages cannot fix polynomial or above complexity issues.

This is true. But once you have fixed all of your algorithmic issues, if your language is slow, you're completely stuck at that point. You have hit a performance ceiling.

Personally, I would rather work in a language where that ceiling is higher than it is in JavaScript.

chubot 2 days ago

Yeah but the application we're talking about here is JavaScript tools, or more generally "language processors" / AST-based workloads

These are very different than your average JavaScript program

And that's exactly where it starts to be the case that JavaScript semantics are the issue

Take it from Lars Bak and Emery Berger (based on their actions, not just opinions): https://lobste.rs/s/ytjc8x/why_i_m_skeptical_rewriting_javas... :)

gagaq 2 days ago

> I think the right answer is a sound typed language.

What do you mean by a "sound typed language". Go and Java have unsound type systems, and run circles around JS and Dart. Considering your involvement with Dart, I find contradictory information [1].

[1] - https://github.com/dart-lang/language/issues/1461

munificent 2 days ago

> What do you mean by a "sound typed language".

I mean that if the type checker concludes than an expression or variable has type T, then no execution of the program will ever lead to a value not of type T being observed in that variable or expression.

In most languages today, this property it enforced with a combination of static and runtime checks. Mostly the former, but things like checked casts, runtime array covariance checks, etc. are common.

That in turn means that a compiler can safely rely on the type system to generate more efficient code.

Java intended to have a sound type system, but a hole or two have been found (which are fortunately caught at runtime by the VM). Go's type system is sound as far as I know. Dart's type system is sound and we certainly rely on that fact in the compiler.

There is no contradictory information as far as I know, but many people seem to falsely believe that soundness requires zero runtime checks, which isn't the case.

svieira 20 hours ago

> which are fortunately caught at runtime by the VM

At least one of them isn't, but that one is in a crufty old area of the code that most people don't care too much about:

https://blog.devgenius.io/java-106-why-does-sneakythrows-wor...

gagaq 2 days ago

[flagged]

gagaq 2 days ago

[flagged]

steve_adams_86 2 days ago

I’ve written quite a bit of tooling in JS, and I genuinely enjoy the language, but I feel like Rust and Go are a godsend for these types of tools. I will sometimes prototype with TypeScript, but if something requires massive concurrency and parallelism, it’s unlikely I’ll stick with it.

I wonder if the author would feel differently if they spent more time writing in more languages on tooling like this. My life got a lot easier when I stopped trying to write TypeScript everywhere and leveraged other languages for their strengths where it made sense. I really wanted to stick to one language I felt most capable with, but seeing how much easier it could be made me change my mind in an instant.

The desire for stronger duck typing is confusing to me, but to each their own. I find Rust allows me to feel far, far more confident in tooling specifically because of its type system. I love that about it. I wish Go’s was a bit more sane, but there are tons of people who disagree with me.

bluGill 2 days ago

> The desire for stronger duck typing is confusing to me, but to each their own

I really like duck typing when I'm working on small programs - under 10,000 lines of code. Don't make me worry about stupid details like that, you know what I mean so just do the $%^#@ thing I want and get out of my way.

When I work with large programs (more than 50k lines of code - I work with some programs with more than 10 million lines and I know of several other projects that are much larger - and there is reason to believe many other large programs exist where those who work on them are not allowed to talk about them) I'm glad for the discipline that strong typing forces on me. You quickly reach a point in code where types save you from far more problems than their annoyance costs.

nobodyandproud 2 days ago

A language that goes from prototype-quality (duck typing, dynamic, and interpreted) to strict static compile checks would be nice.

I can’t think of any in the mainstream, however.

pjmlp 2 hours ago

Common Lisp comes to mind, but I guess it is debatable to consider it mainstream.

Spivak 2 days ago

Isn't that TypeScript or more generically "type hints" in other languages? If all you care about is that your program is valid for some gradually increasing subset of your code at compile time then these work great.

nobodyandproud 1 day ago

I was envisioning a system or some other compiled language, but you’re right. I overlooked Typescript and it indeed comes close.

bluGill 2 days ago

i don't do javascript, but I know from experience adding const to c++ is impossible I expect the similar for types

Joker_vD 2 days ago

> you know what I mean just do the $%^#@ thing I want

Yeah, it's just that about 10k LoC, as I've also noticed, you don't actually know what you yourself mean! It's probably because such amount of code is almost never written in one sitting, so you end up forgetting that e.g. you've switched, for this particular fields, from a stack of strings to just a single string (you manage the stacking elsewhere) and now your foo[-1] gives you hilarious results.

romwell 2 days ago

Types in the end are contacts you make with yourself, enforced by the compiler.

A weak type system gives you the freedom to trick yourself.

I don't feel it's a feature.

yesiamyourdad 2 days ago

I just skimmed the article but the author had a statement about JS being "working class" in that it didn't enforce types and that he dislikes TS for that reason. Rust is completely anathema to that attitude, you have to make a LOT of decisions up front. People who don't see the value in a compiler are never going to like working in Rust. The author is completely satisfied with optimizing hacks in the toolchain.

cies 2 days ago

I also though rewrites of JS projects were only in part motivated by perf gain. Sure they were the most advertised benefits of the rewritten tools, as that communicates a benefit for the users of those tools.

> I find Rust allows me to feel far, far more confident in tooling specifically because of its type system.

Usually the JS projects become really hard to work on the growing up. Good JS needs a lot of discipline on the team of devs working on it: it get messy easily and refactoring becomes very hard. Type systems help with that. TypeScript helps, but only so much... Going with a languages that both has a sound type system (like Rust) and allows lots of perf improvements (like Rust) becomes an attractive option.

Vinnl 2 days ago

"Skeptical" doesn't mean completely against their usage. From the author in the comment section:

> “Embarrassingly parallel” tasks definitely make a lot of sense to do in Rust.

steve_adams_86 2 days ago

I noticed that, and I was left kind of confused. My experience might be limited, but operating on thousands of files and performing multiple reads or writes on them over and over seems exactly like the type of thing a lot of JS tooling does, so I’m not really sure where the author decides that JS is no longer the right fit. I don’t see why that doesn’t dispel skepticism right off of the bat.

LordHeini 2 days ago

As someone who as written a lot of Go and trained a couple of people in it.

The "more difficult" in this quote makes me somewhat angry.

`This breaks down if JavaScript library authors are using languages that are different (and more difficult!) than JavaScript.`

JS is absolutely not easy!

It is not class oriented but uses funky prototypes, it has classes slapped on PHP-Style.

Types are bonkers, so someone bolted on TypeScript.

It has a dual wield footgun in the form of null/undefined, a repeat of the billion dollar mistake but twice!

The whole Javascript tooling and ecosystem is a giant mess with no fix in sight (hence all the rewrites).

The whole JavaScript ecosystem is ludicrously complicated with lots of opinions on everything.

Tooling is especially bad because you need a VM to run stuff (so lots of rewrites).

This is why Java never got much traction in that space too.

Go for example is way easier to learn than Javascript.

Here i mean to a level of proficiency which goes beyond making some buttons blink or load a bit of stuff from some database.

Tooling just works. There is no thought to spend on how to format stuff or which tool to use to run things.

And even somewhat difficult (and in my opinion useless) features like classes are a absent.

Want to do concurrency? Just to `go func whatever()`. Want it to communicate across threads? Use a channel it makes stuff go from A -> B.

Try this in JS you have to know concepts like Promises, WebWorkers and a VM which is not really multithreaded to begin with.

SebastianKra 22 hours ago

I think you're misunderstanding the billion dollar mistake. It was not statically tracking null-references. In JS, everything is dynamic so it doesn't apply, and TS does check them.

> My goal was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler. But I couldn't resist the temptation to put in a null reference

https://en.wikipedia.org/wiki/Tony_Hoare

(Emphasis mine)

WD-42 2 days ago

Agree that JS is not easier these days. It only seems easier because we all already know it.

ForHackernews 2 days ago

This author already has JS Stockholm syndrome and at least acknowledges that up front.

thomasvogelaar 2 days ago

I don't buy the argument that a lot of the performance jumps from rewrites comes from developers writing more optimised code.

I've worked on multiple rewrites of existing systems in both JS and PHP to Go and those projects were usually re-written strictly 1:1 (bugs becoming features and all that). It was pretty typical to see an 8-10x performance improvement by just switching language.

xandrius 2 days ago

Exactly the same experience.

For a smallish batch processing script I had written in node, I just fed it to chatgpt and got the golang version. It went from being unusable with over 100K records to handling 1M on exactly the same machine.

And only then I started adding things like channels, parallelism, and smart things.

thomasvogelaar 2 days ago

Now that there's no perfect parity to maintain we've started optimising the Go versions as well. Multiple 2x performance improvements once we started doing this, on top of the original performance improvements. This translates to insane cost savings when you're working at scale.

Joker_vD 2 days ago

Yeah, it reminds me about all those old "Haskell can be faster than C!" posts that used to be very popular. Sure, some exquisite, finely-crafted Haskell code can be faster than a plain, dumb, straightforward, boring C code. But if you compare plain, dumb, straightforward, boring Haskell code with plain, dumb, straightforward, boring C code, the latter will be faster pretty much always.

nineteen999 2 days ago

Plus it will be readable by a much larger percentage of working programmers.

tinco 2 days ago

I'd rather have a code base I'm going to be working on in a language I haven't learned yet, than having it be in C or C++ if it's of any significant size. Learning a new language is small thing, all things considered, especially if it's a well designed one like Haskell.

Spending a week or two getting familiar with the way things are done in a language, and then gradually become effective in it and the specific codebase I would be working on for me at least would beat having to work in an environment with 50 years worth of irreconcilable technical debt inherent to the language.

fredrikholm 1 day ago

I agree with you fully, but I've also tried to onboard people to F# and Haskell and... unless you're the self selecting person that enjoys (typed) functional programming, the pushback you get from the other ~95% of developers is extremely strong.

If your stack is FP-ish, and you hire FP-ish developers, it's fine. But having non-FP devs write Haskell? Maybe I've been unlucky, but it's near impossible in my experience.