Live data from Hacker News

Why Discord is switching from Go to Rust (2020)

discord.com

41–50 of 60 posts

Re: Why Discord is switching from Go to Rust (2020)

#41
post #13

How illuminating. From CloudFlare posts, I had been under the impression that Go's gc was incredibly unintrusive, near-real time performance for applications operating in increments of a few hundred milliseconds. For example, CloudFlare uses Go to analyze network traffic. Yes, Rust provides a more predictable, faster memory management model than Go. At the expense of unpredictable, expensive memory leaks triggering a…

Hmm, well Go itself has gone through a ton of revisions where the GC saw large improvements. And other languages coming up are experimenting with various types of GCs. Its really up to the use case though.

With discord, I imagine a big reason why Rust was considered as an alternative to Go is because they already have a substantial Elixir codebase. Rust and Elixir have a very easy time communicating with one another via Erlang NIFs (native function interfaces). You can embed languages like C/C++/Rust into elixir without much overhead. While I've never personally tried do to such a thing with go, I can't imagine its a smooth experience. You'd probably need to use Ports or CNodes for Go simply for this reason.

I love go myself, but one of the biggest turn offs for the language is its FFI support for C and other C connected languages. CGo is a relatively expensive investment when compared to many other comparable alternatives and it should be avoided if possible.

Re: Why Discord is switching from Go to Rust (2020)

#43
post #17

Earlier quoted context omitted.

I don't understand.... isn't this idea (triggering GC more often) explicitly discussed in the article?

I remember when this article came out, everybody was pointing out the fact that they used a go version that was several releases older. Perhaps if the intent wasn't to convince their managers to let them write it in Rust, they would have tried using the latest Go version at the time?

https://news.ycombinator.com/item?id=31021719

Re: Why Discord is switching from Go to Rust (2020)

#44
post #13

How illuminating. From CloudFlare posts, I had been under the impression that Go's gc was incredibly unintrusive, near-real time performance for applications operating in increments of a few hundred milliseconds. For example, CloudFlare uses Go to analyze network traffic. Yes, Rust provides a more predictable, faster memory management model than Go. At the expense of unpredictable, expensive memory leaks triggering a…

Hmm, well Go itself has gone through a ton of revisions where the GC saw large improvements. And other languages coming up are experimenting with various types of GCs. Its really up to the use case though. With discord, I imagine a big reason why Rust was considered as an alternative to Go is because they already have a substantial Elixir codebase. Rust and Elixir have a very easy time communicating with one another…

We use Elixir + Rust in a few select places. But the majority of our Rust code is services that are purely written in Rust.

We use Rust over Go, not only because of the garbage collection issues, but because it's truly a better language in almost every way (once you learn it!)

I will say, Go is much easier to pick up, but in exchange you pay in the long term having a language that actively works against you when you start working on more advanced programs, and a mountain of code that's accumulated over the years that you have to maintain.

We work on high concurrency systems here, and I very much enjoy not ever having to think about "is this thing thread safe" because the compiler is checking that for you. I love being able to use the type system to offer my co-workers powerful, but difficult to misuse libraries. I like having sensible abstractions around concurrent execution.

Like, for example, if you create a channel in go, and for whatever reason, don't try to read from the channel, or give up (because you're racing a timeout), then the goroutine that tries to write to that channel will block forever and leak. In Rust, if you try to write to a channel where there is no longer a receiver, the write to channel will return an error, which you can then choose to handle, or simply ignore depending on your use-case. Of course, you can be wise and allocate your channels with a capacity of 1, but you can also just completely forget that, and start a steady leak of goroutines for the lifetime of your program that the garbage collector won't save you from!

Want to execute many futures with bounded concurrency in Rust and collect the results back into a Vec, but give up if any of the futures fail, or if a timeout is elapsed, and also make sure that all allocated resources are properly dropped and closed in the event that any errors happen? Just combine a futures::stream::StreamExt::{buffer_unordered, collect}, and a tokio::time::timeout, and in a few lines of code you've done it.

Want to do the same in Go? Spawn a pool of goroutines I guess, distribute two channels, one for sending them work, one for receiving work, and don't forget to throw in a WaitGroup, pass a context along to all the goroutines, make sure you don't forget any defers, if you are using a shared resource, make sure it's thread safe, or make sure you're locking/unlocking the appropriate mutex, make sure you size your result channel appropriately or you might leak goroutines and any allocations they hold if your main goroutine that's spawned all that work timed out waiting for the results to come in. Is there a library that does all this for you in Go? I googled "golang run many goroutines and collect their results" and looked at the first page of results, and it's basically the above...

It is no surprise then that we've picked to use Rust pretty seriously. When you're looking to build reliable systems with serious speeds and massive concurrency, you pick the best tool for the job. That for us is Rust, not Go. And for our real time Distributed systems, we pick Elixir, because BEAM/OTP is just so dang good.

Re: Why Discord is switching from Go to Rust (2020)

#45
post #13

How illuminating. From CloudFlare posts, I had been under the impression that Go's gc was incredibly unintrusive, near-real time performance for applications operating in increments of a few hundred milliseconds. For example, CloudFlare uses Go to analyze network traffic. Yes, Rust provides a more predictable, faster memory management model than Go. At the expense of unpredictable, expensive memory leaks triggering a…

> At the expense of unpredictable, expensive memory leaks triggering application termination.

Rust’s borrow checker does defend against it as well for safe rust, unless you are doing something very stupid, this is just false.

Re: Why Discord is switching from Go to Rust (2020)

#46
post #44

Earlier quoted context omitted.

Hmm, well Go itself has gone through a ton of revisions where the GC saw large improvements. And other languages coming up are experimenting with various types of GCs. Its really up to the use case though. With discord, I imagine a big reason why Rust was considered as an alternative to Go is because they already have a substantial Elixir codebase. Rust and Elixir have a very easy time communicating with one another…

We use Elixir + Rust in a few select places. But the majority of our Rust code is services that are purely written in Rust. We use Rust over Go, not only because of the garbage collection issues, but because it's truly a better language in almost every way (once you learn it!) I will say, Go is much easier to pick up, but in exchange you pay in the long term having a language that actively works against you when you…

> We use Rust over Go, not only because of the garbage collection issues, but because it's truly a better language in almost every way (once you learn it!)

What about complexity? How does "enterprise Go" code compare to "enterprise Rust" code? And what about the tooling. The other threads here are dwelling on GC, and latency, and threading and so on.

One of Go's selling points is that it tends to force writing simple-to-read code.

My general experience in C++/C#/Java/Kotlin is once a code base gets beyond a certain size and number of developers, without any discipline, it becomes a hot mess.

Re: Why Discord is switching from Go to Rust (2020)

#47
post #20

Earlier quoted context omitted.

or you know; just pace the GC mark and sweep algorithm. which is what go is doing now.

Correct me if I'm wrong, but IIRC pacing would still cause a latency spike, it would just be a more strategically-timed latency spike.

sure - https://github.com/golang/go/issues/44167. you'll see the new design the CPU util only increases in GC CPU utilizations when you're actually allocating heavily. which makes sense you're doing more work. this should completely resolve the problem discord had; since their system was in a steady state.

Re: Why Discord is switching from Go to Rust (2020)

#48
post #20

Earlier quoted context omitted.

or you know; just pace the GC mark and sweep algorithm. which is what go is doing now.

You are always going to have some kind of latency spike with a sweeping GC; even if that spike is tiny.

not really. if you're in a steady state (like discord was) you wouldn't see any spikes. you'd have a consistent utilization. if you start allocating heavily then you would potentially see an increase. which makes sense, you're increasing your workload, utilization needs to increase. but still not necessarily a 'spike'

Re: Why Discord is switching from Go to Rust (2020)

#49
post #11

Earlier quoted context omitted.

Yes we are using rust in a big way. We have multiple teams now full time working on Rust. It is being used on both the client and server, as native modules, web assembly, and also native rust services and NIFs that embed themselves in our elixir services. It has been an incredible success. I plan to blog more about it in the coming months. Our usage of Rust is continuing to grow, and if you check out our jobs page, y…

I love Rust elixir Nifs. Gives you the best of both worlds to be honest. Highly fault tolerant code with fast computation. Only downside is that it can't really handle extreme crashes like a native process can.

Erlang/Elixir + Rust is an awesome couple. For the downside you mentioned, depending on the use case, it could be interesting to use Rust as a node: https://github.com/sile/erl_dist

Re: Why Discord is switching from Go to Rust (2020)

#50
post #27

Earlier quoted context omitted.

Rust as a language does not protect against memory leaks - std::mem::forget even explicitly does so. Generally garbage collected languages do, so trading go for rust increases the risk of having memory leaks.

You are invoking std::mem::forget which is explicitly for circumventing destructor execution and then complaining about leaks. Okay. The documentation page for std::mem::forget goes through all the alternatives you should try before resorting to std::mem::forget. Now, perhaps std::mem::forget should be marked unsafe. However, you don't just "accidentally" run std::mem::forget. BTW, one of the problems with GC languag…

Doing std::mem::forget is not unsafe as you cannot get any sort of undefined behavior which is what Rust protects you from [0].

Leaking is pretty safe, not always desired but definitely not dangerous like random pointers derefs.

But as OP says, leaking accidentally is uncommon.

[0] https://doc.rust-lang.org/nomicon/safe-unsafe-meaning.html

Post reply on HN