[HN Gopher] Why I'm skeptical of rewriting JavaScript tools in "...
___________________________________________________________________
Why I'm skeptical of rewriting JavaScript tools in "faster"
languages
Author : todsacerdoti
Score : 50 points
Date : 2024-10-20 21:25 UTC (1 hours ago)
(HTM) web link (nolanlawson.com)
(TXT) w3m dump (nolanlawson.com)
| bryanrasmussen wrote:
| the big issue here is the debuggability by having all your
| dependencies in the same language, and it's not even like these
| rewrites will all be in the same performant language for you to
| learn, so essentially if you are using a wasm compiled dependency
| you are not likely to be able to go into that dependency's code
| and figure out where the library author has messed up or what you
| have misunderstood from the documentation.
| Kinrany wrote:
| The solution to that is dependencies that work
| bawolff wrote:
| Does the dependency that always works and has no bugs also
| come with a free rainbow and unicorn?
| bryanrasmussen wrote:
| I sure hope so - otherwise how would I know the dependency
| I installed was going to always work?
| bawolff wrote:
| Yeah, i agree. I think there is a time where rewriting in a
| faster language is useful (just like how handcrafted assembly is
| still a thing), but most of the time you are very far away from
| the point where that is neccesary.
|
| I also think there is an element of, "rewrite in rust" is just
| easy to say, where changing data structures or whatever requires
| analysis of the problem at hand.
| MrHamburger wrote:
| It is analogues discussion to C vs Rust. Sure Rust is memory
| safe, but whole ecosystem I am using today is C based.
| Compiler, SDK, drivers, RTOS, ... Nobody sane is going to
| rewrite it for the sake of rewriting it into a different
| language.
| jpalawaga wrote:
| Anyone who has done a programming contest, advent of code, etc
| knows that the language doesn't matter so much as your algorithm.
|
| Yes, the language can bring a nice speed up, or might give you
| better control of allocations which can save a lot of time. But
| in many cases, simply picking the correct algorithm will deliver
| you most of the performance.
|
| As someone who doesn't JavaScript a lot, I'd definitely prefer a
| tool written in go and available on brew over something I need to
| invoke node and its environment for.
| tyree731 wrote:
| Lots of very smart people have worked very hard on Python tools
| written in Python, yet the rust rewrites of those tools are so
| much faster. Sometimes it really is the programming language.
| anyfoo wrote:
| Choosing the right algorithm effectively means optimizing
| runtime complexity. Then, once runtime complexity is fixed
| with the right algorithm, you're still left with a lot of
| constant factors that O-notation deliberately ignores (it's
| only about growth of the runtime). Sometimes, optimizing
| those constant factors can be significant, and then the
| choice of language matters. And even some details about the
| CPU you are targeting, and overall system architecture.
| o11c wrote:
| Often languages like Javascript and Python don't _allow_
| optimal runtime complexity, because the types baked in to
| external interfaces fundamentally disallow the desired
| operation. And these languages are too slow to rewrite the
| core logic in the language itself.
|
| (but of course, the vast majority of the code, even in
| widely used tools, isn't properly designed for optimization
| in the first place)
|
| I only dabble in javascript, but `tsc` is abominable.
| charrondev wrote:
| In the JavaScript world a lot of speed up comes from 3 major
| things as far as I can tell:
|
| - easier concurrency. - the fact that things are actually
| getting rewritten with the purpose of speeding them up. - a
| lot of the JS tooling getting speedups deals with heavily
| with string parsing, tokenizing, generating and manipulation
| of ASTs. Being able to have shared references to slices of
| strings, carefully manage when strings are copied, and have
| strict typing of the AST nodes you enable things to be much
| faster than JavaScript.
| jvanderbot wrote:
| This is a very nice counterexample, but it's not actually a
| counter example without an example.
|
| Also, this was a thing before Rust. I've rewritten several
| things in C or Cpp for python back ends, and most pytbon
| performance-critical code is already an API to a shared
| library. You'd be surprised to run OR tools and find Fortran
| libraries loaded by your python code.
| runesoerensen wrote:
| Ruff is one example https://astral.sh/ruff
| jampekka wrote:
| Python is really really slow compared to JS though.
| gaganyaan wrote:
| CPython is (though it's slowly getting better). Pypy is
| amazingly fast
| zeroonetwothree wrote:
| I once worked on a Python system that had 50 machines
| dedicated to it. We were able to rewrite it in a more
| performant language such that it easily ran on one machine.
| This also allowed us to avoid all the issues distributed
| systems have.
|
| So yeah, Python is not great for systems programming
| worik wrote:
| > Lots of very smart people have worked very hard on Python
| tools written in Python
|
| Yes, I agree that is very sad
|
| Python is achingly slow. I know the Python people want to
| address this, I do not understand. Python makes sense as a
| scripting/job control language, and execution speed does not
| matter.
|
| As an application development language it is diabolical. For
| a lot of reasons, not just speed
| noname120 wrote:
| It's not just a matter of "picking the correct algorithm".
| Algorithmic-interview exercises are algorithmic-interview
| exercices. They are barely related to real-world software
| engineering.
| anyfoo wrote:
| Choosing the right algorithm is usually the prerequisite for
| fast code. Optimizing the constant factors is often pretty
| useless if you pick an algorithm with a runtime that grows
| quadratically, when there are much better options available.
| noname120 wrote:
| What makes you think that the sluggishness of these tools
| is in any way related to not "choosing the right
| algorithm"?
| anyfoo wrote:
| What makes you think they're not? I don't know why these
| tools are sluggish, but I disagree with the notion that
| algorithms don't matter for "real-world software
| engineering".
|
| The world is full of slow software because one chose the
| wrong algorithm:
| https://randomascii.wordpress.com/2019/04/21/on2-in-
| createpr...
| https://randomascii.wordpress.com/2019/12/08/on2-again-
| now-i...
| https://randomascii.wordpress.com/2021/02/16/arranging-
| invis... ...
| magicalhippo wrote:
| While picking the right algorithm seldom comes up in most
| programmers day-to-day activities, being aware of big-Oh and
| the performance guarantees/characteristics of the libraries
| you use most certainly _should_.
|
| I don't care if you don't know how to write a merge sort from
| scratch. I do care about you knowing not to write an O(n^2)
| loop when it can be avoided.
| tightbookkeeper wrote:
| Exactly. What do you do when you have the right algorithm and
| it's too slow (very typical for linear problems that require
| visiting each item).
| anyfoo wrote:
| You optimize the constant factors, e.g. the runtime of the
| inner loops. But this requires you to choose a sane
| algorithm in the first place.
|
| Some problems are much more complicated, where you have to
| take, for example, locality (cache hierarchy etc.) and
| concurrency considerations like lock contention into
| account. This may affect your choice of algorithm, but by
| the time you reach that, you've almost certainly thought
| about the algorithm a lock already.
| tightbookkeeper wrote:
| > knows that the language doesn't matter so much as your
| algorithm.
|
| I know what you're referring to but these problems have also
| taught me a lot about language performance. python and JS array
| access is just 100x slower than C. Some difficult problems
| become much harder due to this limitation.
| jampekka wrote:
| JS array access is a lot faster than Python array access. JS
| is easily within magnitude of C and can be even about as fast
| with typed arrays or well JITable code.
| tightbookkeeper wrote:
| > JS is easily within magnitude of C
|
| Typed arrays help a lot, but I'm still doubtful. Maybe it
| all the processing is restrict to idioms in the asm.js
| subset? And even then you're getting bounds checking.
| hawski wrote:
| In higher level languages your code may allocate memory or
| trigger a GC pass or other smartness in unexpected places. This
| may cause slowdowns you may not have control over or may change
| from version to version or vendor to vendor. It is often easier
| to manage in "faster" languages. Good algorithm may not be
| enough.
| zeroonetwothree wrote:
| The types of problems in those contests are meant to highlight
| algorithms. In the real world you might have a trivial
| algorithm but a huge input size, where the constant factor
| matters much more.
| moomin wrote:
| Here's the thing: languages like C#, Java and Rust all have
| extensive libraries and packages that implement many common
| data structures and algorithms well. With all due respect to
| the incredible work that goes into projects like lodash,
| JavaScript does not. (Nor does C, for that matter.)
| jongjong wrote:
| I also love JavaScript.
|
| It's true, it has some really bad parts but you can avoid them.
|
| If I could design the perfect language for myself, it would have
| the syntax of JavaScript and the portability of JavaScript but it
| would use Python's strong duck typing approach.
| anyfoo wrote:
| What have static type systems ever done to you, that you avoid
| them so much?
| bryanrasmussen wrote:
| most static type systems are verbose, probably due to
| linguistic verbosity, so one obvious thing that static type
| systems have probably done to a lot of people is given them
| pain from typing so much.
| anyfoo wrote:
| I don't feel it's so much typing. Especially for the
| clarity and, most importantly, safety and correctness I get
| back. I'd rather type 3 1/2 seconds more than debug a dumb
| type issue for half an hour.
|
| It gets _really_ old to get something like "NoneType does
| not have blah" in a deeply nested, complicated data
| structure in python, but obviously only at runtime and only
| in that hard to hit corner case, when all you did is forget
| to wrap something in the right number of square brackets in
| some other part of the code.
|
| I haven't fully given up on python, but I only deal with it
| using mypy, which adds static typing, anymore.
| jwells89 wrote:
| A bit of extra verbosity as added by static typing can
| also be immensely helpful for trawling through and/or
| learning an unfamiliar codebase, especially in the
| absence of an IDE or debugging environment (e.g. browsing
| code on GitHub or in a filemanager).
|
| For instance, take function definitions. By just adding
| types to the function's arguments, you're potentially
| saving the reader a ton of time and mental overhead since
| they don't have to chase down the right the chain of
| function calls to figure out what it is exactly that's
| getting passed in.
| dbrueck wrote:
| Not the OP, but the appeal of languages like JS has a lot to
| do with developer productivity. I write gobs of JS and Python
| code and the _finished_ programs and libraries can be
| strongly and statically typed end-to-end. I just don 't want
| to be forced to do it in cases when it doesn't really make a
| difference, and I don't want to waste time on it when I'm
| still figuring out the design.
|
| My hope is one of the Next Big Things in programming
| languages is the widespread adoption of incremental typing
| systems.
|
| So during the early stages of dev you get the productivity
| benefits of dynamic and loose/duck typing as much as you
| want, and then as the code matures - as the design firms up -
| you begin layering in the type information on different parts
| of the program (and hopefully the toolset gives you a jump
| start by suggesting a lot of this type info for you, or maybe
| you specify it only in places where the type info can't be
| deduced).
|
| Then those parts of the program (and hopefully eventually the
| entire program) are strongly and statically typed, and you
| get all of the associated goodies.
| singpolyma3 wrote:
| JavaScript isn't really all that portable? Heck just making it
| run on the different JS engines and runtimes is a big pain
| sometimes
| o11c wrote:
| I can't even figure out how to write typescript that
| conditionally uses browser-only or node-only libraries
| depending on which environment it's in. My current best guess
| is to write 2 completely independent typescript projects that
| happen to point to the same source files?
|
| Let me cross-compile a C++ project any day ...
| anyfoo wrote:
| > I've written a lot of JavaScript. I like JavaScript. And more
| importantly, I've built up a set of skills in understanding,
| optimizing, and debugging JavaScript that I'm reluctant to give
| up on.
|
| It's not that hard to do the same for a less terrible language.
| Choose something markedly different, i.e. a low level language
| like rust, and you will learn a lot in the process. More so
| because now you can see and understand the programming world from
| two different vantage points. Plus, it never hurts to understand
| what's going on on a lower level, without an interpreter and eco-
| system abstracting things away so much. This can then feed back
| into your skills and understanding of JS.
| FridgeSeal wrote:
| I swear some JS devs will go out of their way to avoid learning
| anything else, whilst simultaneously and breathlessly espousing
| that we rewrite everything else in JS.
| oneweekwonder wrote:
| > Any application that can be written in JavaScript, will
| eventually be written in JavaScript. - Jeff Atwood (2007)
| tylerchilds wrote:
| i swear some non js devs will go to extreme lengths to
| demonstrate solutions that will never run on another machine
| instead of writing js
| anyfoo wrote:
| Why would they never run on another machine? It's not that
| hard to write portable code, and done very often. Nowadays
| for example, you rarely ever think about whether you're on
| arm or x86.
|
| If you write non-portal code, there might be an important
| reason (like writing OS components, which you won't do in
| JS).
| tylerchilds wrote:
| almost every time code doesn't run on my machine, the
| root cause is a political disagreement with a c-compiler
| author three layers below my actual problem.
|
| javascript doesn't have a compiler is my main point.
| TacticalCoder wrote:
| > I swear some JS devs will go out of their way to avoid
| learning anything else, whilst simultaneously and
| breathlessly espousing that we rewrite everything else in JS.
|
| The JStockholm syndrome.
| mardifoufs wrote:
| It's usually the opposite. And the post is specifically about
| making JavaScript tools, why would you not expect them to be
| written in JS? I guess not making tools for say, c# devs in
| c# would also be bad?
| captnObvious wrote:
| I think we're reading too far into the authors impostor
| syndrome.
|
| He's making contributions in Rust already. His opinion isn't
| invalid just because he has a bias, he opens by acknowledging
| his bias.
| jampekka wrote:
| Hopefully the lot includes that writing stuff in low level
| languages isn't worth the pain most of the time.
| winwang wrote:
| Curious what you mean by "most" (I'm agnostic/unlearned on
| the statistics tbh). I "feel" like it doesn't happen too
| often when it's not either already low-level or the supposed
| extra performance is likely worth it.
|
| Like, I can't imagine most people using Javascript would
| _want_ to rewrite in Rust without some decent reason.
| noname120 wrote:
| > I just don't think we've exhausted all the possibilities of
| making JavaScript tools faster
|
| Rewriting in more performant languages spares you from the pain
| of optimization. These tools written in Rust are somehow 100x as
| fast despite not being optimized at all.
|
| JavaScript is so slow that you _have_ to optimize stuff, with
| Rust (and other performant languages) you don 't even need to
| because performance just doesn't bubble up as a problem at all,
| letting you focus on building the actual tool.
| evanjrowley wrote:
| >JavaScript is so slow that you have to optimize stuff
|
| This raises the question, is JavaScript more prone to premature
| optimization?
| noname120 wrote:
| Well, can we really call it premature optimization if it's
| needed?
| dpritchett wrote:
| Reminds me of using Ruby ten years ago and having to
| contend with folks who wanted to default to using the
| string literal style over another because it was known to
| be more performant at scale. That awkward stuff surfaces
| earlier with some languages than with others.
| ignoramous wrote:
| Being a statically-typed compiled language has its perks
| (especially when doing systems programming). Regardless, JS
| runtimes can and will push forward (like JVM / ART did), given
| there's healthy competition for both v8 & Node.
| noname120 wrote:
| JavaScript, Python, Lua, I don't see any dynamic language
| with good performances. Do you have examples?
| dkersten wrote:
| Lua with LuaJIT has pretty good performance. With that
| said, I spent today writing in C++, so I do agree with the
| overall sentiment.
| metadat wrote:
| "Good" compared to what? All the mentioned languages keep
| getting more performant year-over-year, but in the medium
| future scripting languages are unlikely to reach the
| performance levels of C, Rust or other low-level languages.
|
| Wouldn't it be amazing though? Maybe some combination of
| JIT and runtime static analysis could do it.
|
| Personally, I never assign different types to the same
| variable unless it's part of a union (e.g. string |
| HTMLObject | null, in JS).
|
| It would probably require getting rid of `eval' though,
| which I am fine with. On average, eval() tends to be
| naughty and those needs could be better met in other ways
| than blindly executing a string.
| jvanderbot wrote:
| Someday soon I hope webasm gets another decent compiled
| language targeted for JS speedups. Something interoperable with
| JS.
|
| For analogies, look no further than ASM in the early days and
| the motivations that brought us C, but with the lessons learned
| as well.
|
| Rust is fine for this, except for interoperability.
| metadat wrote:
| It looks like Rust can interop with JS via WebASM?
|
| https://stackoverflow.com/questions/65000209/how-to-call-
| rus...
| jvanderbot wrote:
| Of course that's why we're discussing it. I'm referring to
| stronger interop like how you can embed ASM in C, and
| therefore CPP.
|
| Like a JS/TS that can have compiled blocks specified in the
| same language, preferably inline? I'm reaching here.
| dan-robertson wrote:
| I think there's a lot of bias in the samples one tends to see:
|
| - you're less likely to hear about a failed rewrite
|
| - rewrites often gain from having a much better understanding
| of the problem/requirements than the existing solution which
| was likely developed more incrementally
|
| - if you know you will care about performance a lot, you
| hopefully will think about how to architect things in a way
| that is capable of achieving good performance. (Non-cpu
| example: if you are gluing streams of data with processing
| steps together, you may not think much about buffering; if you
| know you will care about throughput, you will probably have to
| think about batching and maybe also some kind of fan-
| out->map->fan-in; if you know you will care about latency you
| will probably think about each extra hop or batch-building
| step)
|
| - hopefully people do a bit of napkin math to decide if
| rewriting something to be faster will achieve the goals, and so
| you only see the rewrites that people thought would be
| beneficial (because eg you're touching a lot of memory so a
| better memory layout could help)
|
| I feel like you're much more likely to see 'we found some
| JavaScript that was too useful for its own good, figured out
| how to rewrite it with better algorithms/data structures,
| concurrency, and sims instructions, which we used rust to get'
| than 'our service receives one request, sends 10 requests to 5
| different services, collects the results and responds; we
| rewrote it in rust but the performance is the same because it
| turns out most of what our service did was waiting'.
| winwang wrote:
| Only semi-relevant, but there's also the fact that lower
| level languages can auto-optimize more deeply -- but that's
| also more my intuition (would love to get learnt if I'm
| wrong).
|
| For example, I'd expect that Rust (or rustc I guess) can
| auto-vectorize more than Node/Deno/etc.
| paulddraper wrote:
| The biggest reason to be skeptical is that these tools are not
| open to extension in the same way that JavaScript is.
|
| Webpack has an enormous community of third-party plugins, it
| would be very hard to do something similar with e.g. Go or Zig.
| klabb3 wrote:
| Right, because tooling is standardized in eg Go. There's no
| custom build pipeline, transpilation hell, or experimental
| language features that are selectively enabled randomly. I'm
| not even against JS, like at all, and I think the majority of
| perf issues can be resolved. However, JS tooling is the prime
| example of where things get truly nightmarish from a software
| development perspective. Webpack being a perfect example of
| this horror.
| postalrat wrote:
| It's also a breeding ground where the best ideas often end
| becoming a sort of standard not only for javascript devs but
| for other langauges as well.
| tightbookkeeper wrote:
| This is funny to me. Go and zig are built with the Unix shell
| in mind - the most extensible and modular system around.
|
| The webpack ecosystem on the other hand is it's own OS.
| dpritchett wrote:
| Maybe for some the appeal of JS is in (hopefully) never
| having to learn Unix?
|
| I've heard several folks say that about Kubernetes, but in my
| experience the *nix core always resurfaces the second things
| get weird.
| tightbookkeeper wrote:
| That certainly can be a benefit. But as we see here it also
| limits your thinking to that ecosystem.
| qianli_cs wrote:
| I'm not sure if JavaScript supports it, but some Python libraries
| allow you to choose whether to install a more optimized binary
| version or the pure Python implementation.
|
| For example, if you install psycopg you'll get a pure Python
| implementation which is easy to debug and hack. But you can also
| install psycopg[binary] to obtain a faster, compiled version of
| the library.
| https://www.psycopg.org/psycopg3/docs/basic/install.html
| jampekka wrote:
| That typically means two totally different implementations, and
| pure Python versions are often unusably slow, so it doesn't
| help much to hack that.
| sksxihve wrote:
| > Whereas if it's written in a native language, I'd need to check
| out the source code and compile it myself - a big barrier to
| entry.
|
| Is it though? Rust/Zig/Go programs are pretty much all incredibly
| easy to checkout and compile, it's one of the big selling points
| of those languages. And at the end of the day how often are
| javascript developers fixing the tooling they use even when it's
| written in javascript?
|
| I've always felt learning new languages give me not only new
| tools to use but shapes the way I think about solving problems.
| timeon wrote:
| I wonder if author is aware that Node.js is not written in
| JavaScript.
| from-nibly wrote:
| > It's very forgiving of types
|
| I lost you here. JavaScript doesn't work around type issues, no
| language really can. It just pushes the type issues to a later
| time.
| porcoda wrote:
| Sometimes it seems that people who write these kinds of pieces
| forget that not everyone in the world does web or even web-
| adjacent work, and node.js is something we don't even consider to
| be part of our ecosystem. Rewriting useful things in non-JS has
| the benefit of letting folks like me who avoid JS like the plague
| use useful tools. Stop assuming everyone wants to get anywhere
| near the JS ecosystem: I've gone 30 years without touching it,
| and plan to continue that streak. Rewriting stuff is great from
| my perspective.
| worik wrote:
| > Stop assuming everyone wants to get anywhere near the JS
| ecosystem
|
| I have been dragged, through straight misrepresentation, into
| the Node.js world.
|
| OMG, awful hardly begins to touch it.
|
| I have not used Go, but as far as I can tell every thing the
| Node.js people do is done better in Go.
|
| I do not recommend Rust. I have a lot of experience with Rust,
| and unless you actually need the real time responsiveness it
| will bog you down.
| cyberax wrote:
| > For another thing: it's straightforward to modify JavaScript
| dependencies locally. I've often tweaked something in my local
| node_modules folder when I'm trying to track down a bug or work
| on a feature in a library I depend on. Whereas if it's written in
| a native language, I'd need to check out the source code and
| compile it myself - a big barrier to entry.
|
| Yeah, JavaScript is sloppy, but you can always monkey-patch it by
| modifying tool-controlled files. Great idea. Not.
|
| JS is just not a good language. The JIT and the web of packages
| made it slightly more usable, but it's still Not Good. There's no
| real way to do real parallel processing, async/await are hellish
| to debug, etc.
|
| It's unavoidable in browsers, but we _can_ avoid using it for
| tools. Look at Python, a native PIP replacement improved build
| times for HomeAssistant by an order of magnitude:
| https://developers.home-assistant.io/blog/2024/04/03/build-i...
| metadat wrote:
| _> I should also acknowledge: there is a perf hit from using Wasm
| versus pure-native tools. So this could be another reason native
| tools are taking the CLI world by storm, but not necessarily the
| browser frontend._
|
| I didn't know about this before, I wonder how much overhead?
|
| The reason I am reluctant to rely on JS tools for anything CLI is
| because of Node.js instability due to version sensitivity and
| impossible-to-fix-without-reinstalling-the-os low level LibC
| errors.
|
| Compared to go, rust, or python, the odds that any given CLI.js
| program will run across my (small) fleet of machines is very low,
| by factor or 10x or more compared to alternatives. Some boxes I
| don't want to reinstall from scratch every 4 years, they're not
| public facing and life is too short.
| a_wild_dandan wrote:
| I'm continually surprised at JavaScript's speed. Seeing JS
| sometimes nipping at the heels of C/rust/etc in performance
| benchmarks blows me away. V8 is such an incredible piece of
| engineering.
|
| In my work, it's hard to justify using something other than JS/TS
| -- incredible type system, fast, unified code base for
| server/mobile/web/desktop, world's biggest package ecosystem for
| anything you need, biggest hiring pool from being the best known
| language, etc.
|
| It's just such a joy to work with, ime. Full-stack JS has been
| such a superpower for me, especially on smaller teams.
|
| The dissonance between how the silent majority feels about JS
| (see, e.g the SO yearly survey), vs the animus it receives on
| platforms like HN is sad. So here's my attempt at bringing a
| little positivity and appreciation to the comments haha.
___________________________________________________________________
(page generated 2024-10-20 23:01 UTC)