But more importantly, the Typescript team themselves [1] picked Golang mostly out of ergonomics and ease of porting at the time. It is becoming more increasingly more to "taste" what ergonomics means. Notably, they did not pick it because they believed it to be the fastest option. But speed was on the mind, giving way to ergonomics and ease of porting. At least, this is my read.
[1] https://github.com/microsoft/typescript-go/discussions/411
https://news.ycombinator.com/item?id=22336284
It is one person and one project, but I found it interesting to read about his experience.
I like Go, but I probably would have tried Rust first because I want pattern matching when implementing languages.
The "shape" of the code would be different?
Notorious examples, the recent Github Copilot runtime, and the Microsoft 365 microservices.
However, it mostly represents a mechanical port of the old codebase to Go. What I haven't seen anyone do is try a true rewrite in Go optimized for performance (whilst keeping a strong emphasis on readability).
Typescript team explicitly mentioned the lack of Typescript specification as one of the reasons to choose Go. Typescript as the language is defined currently by its compiler which was Javascript based. Go port is as close to it as possible while Rust would be harder to reach fully identical behavior.
Once you move beyond interpreters, performance is mostly a property of how much effort you want to put into profiling and optimization, not any specific properties of a programming language (YMMV of course).
For example, in the Breaka Club (https://breaka.club/) editor, which is not presently exposed to kids yet, we define behaviors for characters, props, mosaics (terrain tiles) and items in JSON. But the JSON has type checking and real-time completion as you type. Not naive property auto-suggestion, we have effect types and they're context aware in that you can refer to targets introduced higher in parent constructs of the JSON — and they're fully type checked. If you refer to a target that does not exist in a context, it won't validate and you cannot save the schema.
We use tsgo for development, but the editor (runtime schema validation) is presently stuck on TypeScript 6 because there's no WASM support.
Now, is it nutty that we're using TypeScript for JSON validation? A little. But it's extremely powerful. We're going far beyond what's capable with Zod or ArkType.
Go having a garbage collector isn't necessarily bad, since Wasm has GC, but I think Go's GC can't easily use Wasm GC because Go has interior pointers.
However, it has a relatively large runtime, so TinyGo is often preferred when bundle size needs to be small.
Writing Rust, Zig, or Go, you would still control memory manually, where it matters.
GC absolutely has performance costs, even with minimal allocations, because tracing collectors must scan live objects. This is exactly what this post says. Don't know if its really improved over time in real world cases.
But my main point was that the presence of a GC has nothing to do with how close a language is to the metal. Memory management strategy and low-level capabilities are two separate things.
Yeah but let's be honest; GC languages (Go, Java, C#) usually are slower than systems languages. Systems languages just give you more, low level control over the computer from within your program. You can use that control to improve performance. Eg, you can control data locality, memory access patterns, the emitted assembler, and way more stuff.
Of course you're right - if you misuse arc, you can make your program slow. So don't misuse arc then. Rust gives you lots of options for structuring memory. If you choose badly, that's on you.
The only real choice of language to build the next generation of JS tools in is JS. Anything else is a vote of no confidence in ourselves.
If you wanted to point to their evidence you couldn't because they don't have any.
I would not want a core internet router or a kernel to be implemented in JS. But I am happy it is used elsewhere.
If the argument is that it's not fast enough, JS is actually quite fast: https://mrale.ph/blog/2018-02-03-maybe-you-dont-need-rust-to...
If the argument is "we need to show a 10x boost in raw throughput" then I think we first need to have an argument about why throughput is the right metric as a target for optimization. Throughput is the critical performance measure of a batch processing architecture. IDE's, like web UIs, "feel fast" when they're responsive, which is to say when they can start giving the user access to useful output (and interaction) at the soonest moment the program could possibly be ready to do so. In web perf we might measure this as INP: time from Interaction to Next Paint.
JS won't be winning prizes for throughput, no, but if we completed the move away from a batch processing mindset to an incremental recomputation mindset, and at the same time switched to measuring responsiveness metrics like INP, suddenly the perf characteristics of JS seem a lot more helpful. It's the closest language to the DOM, so when your IDE's interface is built on web technology you'll optimize INP by keeping the data layer in JS: https://code.visualstudio.com/blogs/2018/03/23/text-buffer-r...
There's an even stronger reason than the DOM though to see JS as the "native" layer for perf: plugins. An IDE's selling point is integration, and users want to extend their IDEs by writing Javascript code. Like it or not, JS is the most natural and highly-performant native kernel language for a system of JS plugins.