Rust or go for my networking project

I started learning rust some times ago and i have a project i am currently starting to work on: a small networking project for a p2p file sharing system, someone recommended me Golang but i do not really want to use something other than rust, so i would like to have an honest comparison of the 2 on the networking side.

I know that i may not receive unbiased answers but please try to be as unbiased as possible,

I don't know anything about Go, but if you go for Rust, I just want to make sure that you know that Tokio recently released a Tokio tutorial: https://tokio.rs/tokio/tutorial, because it really is a valuable resource on networking applications in Rust.

2 Likes

Unfortunately I'm new to Rust so I can't say anything about that, but I have quite a bit of experience with Go and I recently wrote something similar to your project (but much simpler, basically just a sub/pub service) and I'm not happy how it turned out and I'm thinking of rewriting it in Rust to see if it gets better.

I have a map of incoming connections and for each connection it holds the TCP connection and several channels (signaling new messages, timeouts, canceled context, closed connection, etc.) and because of Go's channel axioms, especially "A send to a closed channel panics", it takes quite a bit of juggling to make sure that all channels are drained and no goroutines are leaked when a connection is dropped from either side. It's really quite ugly.

I watched a YouTube video of a Rust conference talk. Unfortunately, I can't dig it up now.

He talked about introducing Rust at his company. For the first two tasks they tried with Rust, it was a great success. For the third task, it was painful. That third task was building a network service. I've built a few network services myself, mostly in C++.

Rust is my favorite programming language, and golang is far from it, but I'm always a bigger fan of picking the right tool for the job. Technically, I think golang's go routines are going to make writing a p2p networking project easier than any other language. Spinning up one go routine per connection yields incredibly readable code. Maybe Rust's new async IO will help (I haven't used it), but with my current understanding, I'd choose golang.

Of course, this assumes all else is equal. Non-technical things that should affect the decision include:

  • How many people in your organization know Rust and Go?
  • How much experience do you have with each language?
  • Are there important libraries you need to call written in either language?
1 Like

I don't know so much about Go. But there is a reason for that.

Some years ago I needed to shunt many real-time XML data streams around, do some filtering on them and deliver them to the right clients on web socket and other connections.

Not being such a "server side" guy I set about investigating how to do this.

What I found was that when I implemented a trial model of this in Go it suffered from horrible jitters and apparently unbounded delays. Which I attributed to it's garbage collector but don't know for sure.

I had just heard of node.js which was new on the scene at the time. I thought it was a crazy idea to run a stupid scripting language like Javascript for anything that required performance. Amazingly I was wrong, my node.js implementation of the same thing was only a little slower than the Go one overall. But it's random jitters and extreme stalls were a lot less. We went with node.js and life was good. Which I attributed not only to the new high performance V8 JIT run times but also to it's event driven programming model that did not waste time on thrashing between threads. But again I don't know for sure.

This last year, in a different company, I have been getting into Rust out of curiosity. Turns out I now have systems similar to the above implemented in Rust and working very well. A lot less jitters and faster overall as well. In fact we have basically bet the company on Rust at this point. For server side and for embedded systems, so called "IoT" now a days.

Now, admittedly I find it a lot harder and it takes more time and planning to get anything working in Rust than Javascript/node.js. And likely Go is much easier to churn out as well. But when you put the effort in the results are solid.

1 Like

I have been spinning up one new async task in Rust per connection. Using the tokio crate. Basically the equivalent of go routines.

Very likely the code is not quite as readable as using Go and Go routines but I was surprised that it is far from hideous.

I'm very sure it outperforms go routines in spades.

1 Like

The Go team has put a lot of work into making the GC spikes much more manageable in recent years, so the situation has improved significantly on that front.

I am an aspiring Rustacean and have only read a little about Go.

That said, I am also gathering information about the applicability of Rust on networking. As Go appears as an alternative, after I have a good foundation of Rust I will evaluate also Go.
Nonetheless, I would like to share my current understanding. The usage of Rust or Go (or even other languages) is also bound by what you understand as networking. Go appears to be quite suited to webservices, including all the things for that on the language and standard library. Strength on this area should not come as a suprise, as Go was originally designed to solve Google`s problem.
Rust has some interesting crates on this area, but I still did not have time to evaluate them thoroughly (currently reading the book).
On other areas of networking, like lower layered protocols, binary protocols, custom protocols the control of Rust seems to shine. My understanding is that Go would not be a viable alternative here.

One core and unique advantage of Rust on networking is not to discard: inherent network security. That may not be of interest if your service is not big enough to be a target. But, hey, you do want to grow, right? So why not have it out of the box?

Also, in networking, stability is king. Operators request 5 9s availability and I see Rust can help here.

Since your application somewhat is on the same domain as Dropbox, I was wondering if you came across the following article : https://dropbox.tech/infrastructure/rewriting-the-heart-of-our-sync-engine
I recently read it and found it quite interesting.
That may help you decide on fitness of Rust to your project.

I've worked with Go in the past and the language feels somewhat like C but with garbage collection and light-weight threads. As such, it works well for low-level network operations and people have implemented all sorts of network protocols in Go.

1 Like

Right. I guess I need to do some catch-up and get more informed on Go.
But so far Rust sounds the ideal language for what I have in mind. Thanks for sharing your opinion

I'm not sure what you mean by "low level" networking code. I thought that typically that was all done in C and lives in your Linux kernel of whatever OS you have. Or are we going bare metal here.

What I have done in Rust is both high and low level at the same time! One project involved sucking in streams of data from our NATS messaging serer. That is pretty high level. But those NATS messages comprise and endless stream of raw binary data out of sensors in a complex proprietary protocol/format that requires a lot of frame delimiting, CRC checking, and parsing out bits and bytes into meaningful data.

Despite being very new to Rust when I did that last year it worked a treat soon enough and has worked reliably ever since. Performance is just fine of course and I don't see any high latency jitters as I have seen with Go in the past.

Sure, for most of applications the networking will be done by the OS and presented as some type of socket binding.
But basically, I meant that in some specific network applications like simulator, emulators, test tools, traffic generators, network traffic analysis etc , one would write their own lower layer stacks (e.g. TCP, UDP, IP, eventually Ethernet). For these type of applications C and C++ are fit. And so is Rust.
Also, on very high speed environments (think of 100Gbps on data centers) there is a trend to use more and more DPDK, which is basically a bypass of the OS to be able to increase throughput processing . (DPDK is in C and there is a Rust FFI binding from what I saw). Here again I would see C, C++ and Rust as the languages to go (no pun intended :stuck_out_tongue: )

I'm pretty sure Rust can do it.

In fact here is Jon Gjengset writing TCP in Rust in a live steamed coding session: "Implementing TCP in Rust (part 1)": https://www.youtube.com/watch?v=bzja9fQWzdA&t=5s

Either choice will probably be fine.

I say this specifically because it's P2P. Even if your software scales perfectly, the cheap consumer routers that you might have to go through won't let you open more than 50 connections anyway, and the ADSL and satellite lines that they're connected to won't allow you to upload more than 1 Mbit / second. And if they're on a metered connection, then you won't be able to upload at full speed anyway.

Some users might be better off, but your default settings need to plan for the least common denominator.