Live data from Hacker News

Why Discord is switching from Go to Rust

blog.discordapp.com

561–570 of 670 posts

Re: Why Discord is switching from Go to Rust

#561

Earlier quoted context omitted.

Could you please provide a source for this? Java is very fast and 3X slower is a pretty wild claim.

VMs with JIT like the JVM are only ever really fast/competitive with C in small numerical micro-benchmarks where the code can be hyper-optimized. Most code will be considerably slower due to a lot of factors. Java in particular is a very pointer-heavy language, made up of pointers to pointers to pointers everywhere, which is really bad for our modern systems that often are much more memory latency than CPU constraine…

This stuff is really hard to pin down though. I've been reading these sorts of debates forever.

It's true that pointer chasing really hurts in some sorts of program and benchmark. For sure. No argument. That's why Project Valhalla exists.

But it's also my view that modern C++ programming gets away with a lot of slow behaviours that people don't really investigate or talk about because they're smeared over the program and thus don't show up in profilers, whereas actually the JVM fixes them everywhere.

C++ programs tend to rely much more heavily on copying large structures around than pointer-heavy programs. This isn't always or even mostly because "value types are fast". It's usually because C++ doesn't have good memory management so resource management and memory layout gets conflated, e.g. std::vector. You can't measure this because the overheads are spread out over the entire program and inlined everywhere, so don't really show up in profiling. For the same reasons C++ programs rely heavily on over-specialised generics where the specialisation isn't actually a perf win but rather a side effect of the desire for automatic resource management, which leads to notorious problems with code bloat and (especially) compile time bloat.

Another source of normally obscured C++ performance issues is the heap. We know malloc is very slow because people so frequently roll their own allocators that the STL supports this behaviour out of the box. But malloc/new is also completely endemic all over C++ codebases. Custom allocators are rare and restricted to very hot paths in very well optimised programs. On the JVM allocation is always so fast it's nearly free, and if you're not actually saturating every core on the machine 100% of the time, allocation effectively is free because all the work is pushed to the spare cores doing GC.

Yet another source of problems is cases where the C++ programmer doesn't or can't actually ensure all data is laid out in memory together because the needed layouts are dynamically changing. In this case a moving GC like in the JVM can yield big cache hit rate wins because the GC will move objects that refer to each other together, even if they were allocated far apart in time. This effect is measurable in modern JVMs where the GC can be disabled:

https://shipilev.net/jvm/anatomy-quarks/11-moving-gc-localit...

And finally some styles of C++ program involve a lot of virtual methods that aren't always used, because e.g. there is a base class that has multiple implementations but in any given run of the program only one base class is used (unit tests vs prod, selected by command line flag etc). JVM can devirtualise these calls and make them free, but C++ compilers usually don't.

On the other hand all these things can be obscured by the fact that C++ these days tends only to be used in codebases where performance is considered important, so C++ devs write performance tuned code by default (or what they think is tuned at least). Whereas higher level languages get used for every kind of program, including the common kind where performance isn't that big of a deal.

Re: Why Discord is switching from Go to Rust

#562
post #381

Earlier quoted context omitted.

> The JVM world tends to solve this problem by using off-heap caches. See Apache Ignite [0] or Ehcache [1]. For those who care, I was interested how off-heap caching works in Java and I did some quick searching around the Apache Ignite code. The meat is here: - GridUnsafeMemory, an implementation of access to entries allocated off-heap. This appears to implement some common Ignite interface, and invokes calls to a “G…

Unsafe lets you manipulate memory without any JNI overhead other than when allocating or de-allocating memory, and that is usually done in larger chunks and pooled to avoid the overhead at steady state. Netty also takes advantage of Unsafe to move a lot of memory operations off the java heap. Unsafe was one of the cooler aspects to Java that Oracle is actively killing for, well, no good reason at least.

They aren't killing it. They're steadily designing safe and API stable replacements for its features, with equal performance. That is a very impressive engineering feat!

For instance fast access to un-GCd off heap memory is being added at the moment via the MemoryLayout class. Once that's here apps that upgrade won't need to use Unsafe anymore. MemoryLayout gives equivalent performance but with bounds checked accesses, so you can't accidentally corrupt the heap and crash the JVM.

They've been at it for a long time now. For instance VarHandle exposes various low level tools like different kinds of memory barriers that are needed to implement low level concurrency constructs. They're working on replacements for some of the anonymous class stuff too.

Re: Why Discord is switching from Go to Rust

#563
post #536

Earlier quoted context omitted.

> You have to distinguish between the features available to a Go program as the user writes it and the implementation of the language. I do, I'm just objecting to "Go is implemented in Go".

But on what basis? What part of Go isn't implemented in Go?

I gave an example a bit further up, here [1].

[1] https://news.ycombinator.com/item?id=22240223

Re: Why Discord is switching from Go to Rust

#564

Earlier quoted context omitted.

There's no way to hook into the move, so I don't see how it would be possible, or at least, not with techniques similar to compacting GCs.

Maybe by reifying the indirection? The compacting arena would hand out smart pointers which would either always bounce through something (to get from an indentity to the actual memory location, at a cost) or it'd keep track and patch the pointers it handed out somehow . Possibly half and half, I don't remember what language it was (possibly obj-c?) which would hand out pointers, and on needing to move the allocations…

On top of the cost of the extra pointer lookup, you also run into cache coherency issues when dealing with threading. So then you need to use atomic ops or locks or cache flushing which makes it even more expensive.

Rust is better suited to deal with it since there's a similar issue with refcounting across threads, so you might be able to get away with doing it for objects that are exclusive to one thread.

Re: Why Discord is switching from Go to Rust

#565

Earlier quoted context omitted.

Yes and no. From a theoretical perspective, I suppose that's true, but "garbage collection" tends to mean a non-deterministic collector that does its own thing, and you don't have to think at all about memory. That does not apply to Swift, as of course, you need to understand the difference between strong and weak references. It's unfairly simplistic to couple the two.

But it actually is just garbage collection.

It is but in the context of this discussion it's very clear that they meant a tracing garbage collector, which has a very different cost than atomic reference counting. Or to put it another way: you're technically correct, the worst kind of correct.

Re: Why Discord is switching from Go to Rust

#566

Wait, isn't Go devs said they solved GC latency problems [1]? (from 2015): "Go is building a garbage collector (GC) not only for 2015 but for 2025 and beyond: A GC that supports today’s software development and scales along with new software and hardware throughout the next decade. Such a future has no place for stop-the-world GC pauses, which have been an impediment to broader uses of safe and secure languages such…

That seems to be written by some Manager with slight clue of tech, tbh.

Re: Why Discord is switching from Go to Rust

#568

Earlier quoted context omitted.

3x might be a bit too much today, but it's definitely slower than C. Also to be considered is the VM overhead, not just the executed code. Here are some benchmarks; I'll leave to the experts out there to confirm or dismiss them. https://benchmarksgame-team.pages.debian.net/benchmarksgame/...

However the memory usage difference is astonishing for some of those benchmarks - using 1000x more memory is only acceptable for some situations.

This may be overly cynical, but don’t you have it backwards? 1000x greater memory usage is acceptable for most applications.

There are only a few applications for which it isn’t acceptable.

Just look at all the massive apps built on Electron. People wouldn’t do that if it wasn’t effective.

Re: Why Discord is switching from Go to Rust

#569

Earlier quoted context omitted.

Those people have a really good claim to have the most optimized choice on each language. They've found Java to be 2 to 3 times slower than C and Rust (with much slower outliers). https://benchmarksgame-team.pages.debian.net/benchmarksgame/... On the real world, you won't get things as optimized in higher level languages, because optimized code looks completely unidiomatic. A 3x speedup from Java is a pretty normal c…

Speaking of, I wish there were an "idiomatic code benchmarks game". Some of us want to compare language speed for common use cases vs trying to squeeze every last piece of performance from it.

The problem would be to get a definition of idiomatic code.

Would it be fair to accept an optimization on a language and refuse it on another because it is not idiomatic ?

Re: Why Discord is switching from Go to Rust

#570
post #319

Earlier quoted context omitted.

I am not downvoter, but you should learn the history of the language. Most of the concepts in the language were first implemented long before Google even existed, for systems that were very different from modern ones. It was made by people who had been designing languages for about 40 years now. While some design choices seem weird, they usually have very strong argumentation and solid experience behind them. Also if…

> I am not downvoter, but you should learn the history of the language. What makes you think I haven't been following Go since its inception? > Most of the concepts in the language were first implemented long before Google even existed, for systems that were very different from modern ones. Yes, some of the languages which created those concepts are languages which I've used and which I feel did it better, which is w…

> What makes you think I haven't been following Go since its inception?

Your statement that Go is Google's language. In fact it's Rob Pike's and his team's language.

> Such as?

build speed, cross-platform builds, performance, simplicity of deployment, uniformity of large codebases and documentation, concurrency, learning speed

Post reply on HN