Live data from Hacker News

Why Discord is switching from Go to Rust

blog.discordapp.com

491–500 of 670 posts

Re: Why Discord is switching from Go to Rust

#491
post #407

Earlier quoted context omitted.

I think most people would rate Rust as being closer to Haskell than Java at the type level. Rust traits are very much like Haskell type classes. Java gives you classic OOP, but neither Rust nor Haskell do. Rust generics are much more like Haskell generics than Java generics. Rust and Haskell both have associated types, Java doesn't. Java generics are crippled due to type erasure; Rust and Haskell don't have those lim…

>Java generics are crippled due to type erasure; Rust and Haskell don't have those limitations. Both Rusk and Haskell erase types at runtime. The difference is they don't rely on runtime reflection for anything, so it doesn't hurt them.

In this context "type erasure" means that Java compiles all instances of a generic method to a single implementation that is oblivious to the type parameters. Thus in Java you can't write "T t = new T()" where T is a generic parameter, because the type-erased code doesn't know what T to create.

In Rust, each instance of a generic function is compiled separately and customized as necessary to the specific type parameters. You can write "let t = T::new();" because the compiler will generate a call to the correct constructor for each instance of the generic code. In this sense, types are NOT erased.

Re: Why Discord is switching from Go to Rust

#492
post #423

Earlier quoted context omitted.

And then deal with cross-language FFI boundaries and cross-language builds.

This is what clicked for me on microservices years back. That the language wasn’t important and if I couldn’t do it in python or C, someone else could in Go or Java or etc. Compared to if I wrote something in house entirely in C... lolno

Once you experience protocol buffers it becomes hard to go back.

Re: Why Discord is switching from Go to Rust

#493
post #477

Earlier quoted context omitted.

Huh. I managed to hear about Inferno, but not remember the Limbo part. In that case, Go is Bell Labs' second attempt at Java.

Third, there was also a language I can't remember the name of that happened at the same time as Alef.

Newsqueak?

Re: Why Discord is switching from Go to Rust

#494

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…

> From a purely architectural perspective, I would try to put cacheable material in something like memcache or redis, or one of the many distributed caches out there. But it might not be an option.

Can you speak to why using something like memcache or redis may not be an option?

Re: Why Discord is switching from Go to Rust

#495

This is consistent with my observations of porting Java code to Rust. Much simpler and nicer to read safe Rust code (no unsafe tricks) compiles to programs that outperform carefully tuned Java code.

We detached this subthread from https://news.ycombinator.com/item?id=22240978.

Re: Why Discord is switching from Go to Rust

#497
post #472

Earlier quoted context omitted.

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.

Indeed, but it also doesn’t maintain locality of access nearly as well for young objects (the most commonly manipulated ones) and even older ones that survive.

one related point: the article mentions utilizing rust's BTreeMap, which manages its heap allocations with cache efficiency in mind: https://doc.rust-lang.org/std/collections/struct.BTreeMap.ht....

The guts of BTreeMap's memory management code is here: https://github.com/rust-lang/rust/blob/master/src/liballoc/c.... (warning: it is some of the most gnarly rust code I've ever come across, very dense, complex, and heavy on raw pointers. this is not a criticism at all, just in terms of readability). Anecdotally I've had very good results using BTreeMap in my own projects.

In terms of how the "global" allocator impacts performance, I'd expect it to play a bigger role in terms of Strings (I mean, it's a chat program), and possibly in terms of how the async code "desugars" in storing futures and callbacks on the heap (just guessing, I'm not an expert on the rust async internals).

Re: Why Discord is switching from Go to Rust

#498
post #157

Seems like you were hitting: runtime: Large maps cause significant GC pauses #9477 [0] Looks like this issue was resolved for maps that don't contain pointers by [1]. From the article, sounds like the map keys were strings (which do contain pointers, so the map would need to be scanned by the GC). If pointers in the map keys and values could be avoided, it would have (if my understanding is correct) removed the need…

I was thinking that if their cache is just one large hash table, essentially an array of structs, the GC wouldn't need to scan it. What you say about strings contained in the map would explain their problems, however I don't see the reason for it. Wouldn't you make sure every identifier uses a fixed-length GUID or similar, which would be contained in such a struct used in the array-of-structs?

Re: Why Discord is switching from Go to Rust

#499

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…

> From a purely architectural perspective, I would try to put cacheable material in something like memcache or redis, or one of the many distributed caches out there. But it might not be an option. Can you speak to why using something like memcache or redis may not be an option?

For latency-sensitive services, having to traverse the network to access a shared cache may be too slow. To use the current story as an example, you'd be trading off an occasional 100-millisecond latency spike every 2 minutes for an added 1-2ms of latency for every request.
Post reply on HN