Live data from Hacker News

Why Discord is switching from Go to Rust

blog.discordapp.com

441–450 of 670 posts

Re: Why Discord is switching from Go to Rust

#441

Earlier quoted context omitted.

YeAh BuT wE dOnT wAnT tO hAvE tO tEsT eVeRy oPtIoN!!! - lazy devs and product managers, everywhere

This was the first time I've seen that annoying cAsE meme on HN and I pray it's the last. It is a lazy way to make your point, hoping your meme-case does all the work for you so that you don't have to say anything substantial. Or do you think it adds to the discussion?

It indicates a mocking, over-the-top tone to indicate the high level of contempt I have for my originally-stated paraphrase (and the people who have caused software dev decisionmaking to be that way). So yes, I think it does add to the discussion.

Re: Why Discord is switching from Go to Rust

#442
post #290

Earlier quoted context omitted.

A C app will tend to outperform a Java or Golang app by 3x, so it isn't too surprising.

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 constrained.

A factor of 2-4x to languages like C++ or Rust for most code seems plausible (and even low) unless the limiting factor is external, like network or file system IO.

Re: Why Discord is switching from Go to Rust

#443
post #416

Earlier quoted context omitted.

D, Nim and Crystal all do very well on all metrics. Author finds Rust pretty close but not as maintainable. Interesting that the top 3 (performance close to C++, but more maintainable) all are niche languages that haven't really broken into the mainstream.

Rust won't get a maintainability prize for short programs with simple algorithms. It's Haskell-like features only help on large and complex programs.

They do help library writers, and therefore turn large and complex programs into shorter programs.

Re: Why Discord is switching from Go to Rust

#444

Confused, aren't they losing memory safety? I get for certain core code situations, you want to manage all memory safety yourself (or use built in static GC), but beyond that it seems to me at a higher level you'd rather have the automatic GC. Why burden all of your developers rather than just a core few? I don't think GC issues is a compelling argument to move everything to Rust. I'm not saying there aren't compelli…

Nah, guaranteed memory safety is actually one of Rust's main selling points

Re: Why Discord is switching from Go to Rust

#445
post #413

Earlier quoted context omitted.

Go GC implementation uses memory allocator that was based on TCMalloc (but derived from it quite a bit). They use a free list of multiple fixed allocatable size-classes, which helps in reducing fragmentation. That's why Go GC is non-copying.

I’m not sure I follow. GC implementations that don’t copy (relocate) are inherently subject to the performance cost of “fragmentation” (in the sense of scattering memory accesses over non-adjacent regions). This is a very high price to pay when you’re dealing with modern hardware.

Allocator underneath is keeping track of freed memory, so next allocation has high chance of being squeezed into memory region that has been used before. It's obviously not as good as say GC that relocates after sweep, but at least it doesn't leave gaping holes.

Re: Why Discord is switching from Go to Rust

#446

Looks like the big challenge is managing a large, LRU cache, which tends to be a difficult problem for GC runtimes. I bet the JVM, with its myriad tunable GC algorithms, would perform better, especially Shenandoah and, of course, the Azul C4. The JVM world tends to solve this problem by using off-heap caches. See Apache Ignite [0] or Ehcache [1]. I can't speak for how their Rust cache manages memory, but the thing to…

Maybe I've missed this, but why do they need a particularly large LRU cache? Surely this isn't all one process, so presumably they could reduce spikes by splitting the same load across yet more processes?

Re: Why Discord is switching from Go to Rust

#447
post #32

Earlier quoted context omitted.

It does sound like Discord's case was fairly extraordinary in terms of the degree of the spike: > We kept digging and learned the spikes were huge not because of a massive amount of ready-to-free memory, but because the garbage collector needed to scan the entire LRU cache in order to determine if the memory was truly free from references. So maybe this is one of those things that just doesn't come up in most cases?…

Games written in the Unity engine are (predominately) written in C#, a garbage collected language. Keeping large amounts of data around isn't that unusual since reading from disk is often prohibitively slow, and it's normal to minimize memory allocation/garbage generation (using object pools, caches etc), and manually trigger the GC in loading screens and in other opportune places (as easy as calling System.GC.Collec…

If there's an example of getting great game performance with a GC language, Unity isn't it. Lots of Unity games get stuttery, and even when they don't, they seem to use a lot of RAM relative to game complexity. Kerbal Space Program even mentioned in their release notes at one point something about a new garbage collector helping with frame rate stuttering.

I started up KSP just now, and it was at 5.57GB before I even got to the main menu. To be fair, I hadn't launched it recently, so it was installing its updates or whatever. Ok, I launched it again, and at the main menu it's sitting on 5.46GB. (This is on a Mac.) At Mission Control, I'm not even playing the game yet, and the process is using 6.3GB.

I think a better takeaway is that you can get away with GC even in games now, because it sucks and is inefficient but it's ... good enough. We're all conditioned to put up with inefficient software everywhere, so it doesn't even hurt that much anymore when it totally sucks.

Re: Why Discord is switching from Go to Rust

#448
post #203

Earlier quoted context omitted.

Sure, but that doesn't make Go unsuitable for those tasks on a fundamental basis. Go is very high performance. Whether Go or another language is the best match very much depends on the problem at hand and the especial requirements. Even in the described case they might have tweaked the GC to fit their bill.

GC pauses aside can Go match the performance of Rust when coded properly? Would sorting an array of structs in Go be in the same ballpark as sorting the same sized array of structures in Rust? I don't know a whole lot about how Go manages the heap under the covers.

Sure. That kind of code is very similar in both languages.

Rust will probably be faster because it benefits from optimizations in LLVM that Go likely doesn't have.

Go arrays of structs are contiguous, not indirect pointers.

Re: Why Discord is switching from Go to Rust

#449
post #153

just use an off heap hash table. simple. https://github.com/glycerine/offheap Also, as others have said, lots of big GC improvements were ignored by insisting on go1.9.2 and not the latest.

The graphs are from 1.9.2, but the author said they tried 1.8, 1.9, and 1.10 and saw the same thing.

Re: Why Discord is switching from Go to Rust

#450
post #432

Earlier quoted context omitted.

I was making an assumpotion that using a vector of ARC would be the best way to handle a global LRU cache. Perhaps I should have specified it, but it seemed pretty obvious. Sorry if it wasn’t. If there’s a better way to handle a global LRU cache, I’m all ears.

Assuming only one thread at a time needs to access the LRU cache (not hard with the shared-nothing message passing architecture which we employ here), the lifetime of the object being checked out from the cache is able to be understood at compile time, and we can just use the borrow checker to ensure that it remains that way (we've got a mutable reference to the LRU, and we can use that to get a mutable reference to…

Yes, I'm quite familiar with rust's borrow checking model. I've programmed some in rust, and the rest has been beaten into my head quite thoroughly by Rustaceans. I don't care for Rust, but I understand it.

Locking on one thread at a time seems like a pretty obvious performance flaw. It just doesn't seem like an appropriate design for the given workload (lots of requests, lots of stored items, largely write-only (except for its position in the queue)). It would make a lot more sense to grant multiple threads access the LRU at any given time.

And early optimization and all that aside, creating the LRU in such a way that it can be easily restricted to one thread or opened up makes the most sense to me. Otherwise, you get to re-write the LRU (and all the code which accesses it) if it should be identified as a bottleneck.

Of course, I'm not responsible for the code or truly involved in the design process, so my perspective may be limited.

Post reply on HN