Live data from Hacker News

Taming Go’s memory usage, or how we avoided rewriting our client in Rust

akitasoftware.com

111–120 of 231 posts

Re: Taming Go’s memory usage, or how we avoided rewriting our client in Rust

#111
After using Rust for a few years professionally it's my take that people that really want to use it haven't had much experience with it on real world projects. It just doesn't live up to the hype that surrounds it.

The memory and CPU savings are negligible between Go and Rust in practice no matter what people might claim in theory. However, the side effects of making your team less productive by using Rust is a much higher price to pay than just running you Go service on more powerful hardware.

There are many other non-obvious problems with going to Rust that I won't get into here but they can be quite costly and invisible at first and impossible to fix later.

Simple is better. Stay with Go.

Re: Taming Go’s memory usage, or how we avoided rewriting our client in Rust

#112

Earlier quoted context omitted.

I assume it's tongue-in-cheek; because "rewrite in Rust to improve performance" is such a meme, the headline is subtly calling attention to the fact that this is rarely good advice and certainly not the first lever an engineer should reach for upon running into a performance problem.

> subtly calling attention That's generous. I'd call it clickbait.

Well consider all the projects titled “blah blah blah… written in Rust”

Who gives a shit what it’s written in—what does it do?

Re: Taming Go’s memory usage, or how we avoided rewriting our client in Rust

#113
post #39

The big wins in this article, in what I believe was the order of impact: * They do raw packet reassembly using gopacket, and gopacket keeps TCP reassembly buffers that can grow without bound when you miss a TCP segment. They capped the buffers, and the huge 5G spikes went away. * They were reading whole buffers into memory before handing them off to YAML and JSON parsers. They passed readers instead. * They were usin…

Agree strongly here. These are common sources of memory leaks in any language, and it's very likely that rewriting this code in Rust would lead to the exact same problems. (Other cases on HN, like Discord's in-memory cache and Twitch's "memory ballast" thing, are pretty Go specific -- the identical C program wouldn't have those particular bugs. But, the Go developers read these incident reports and do fix the underly…

> it's an intrinsic Law Of The Universe that if data comes in a X bytes per second, and leaves at X-k bytes per second, then eventually you will use all storage space in the Universe for your buffer,

This is known as Little's Law. Using Little's Law, you know that if the average time spent in queue is more than the average time it takes for a new entry to be added to the queue, then your queue fills up.

Re: Taming Go’s memory usage, or how we avoided rewriting our client in Rust

#114

"How we avoided rewriting in Rust" feels like clickbait given that the answer is "our problems were algorithmic, not language-specific"

A bit yea, but it is somewhat telling that their first instinct was to find a GC "knob" and twist it around until they could go back to ignoring their basic architecture.

Go and Rust are great in that they let you write code at good speed, although, I think this just highlights the well known problems of over optimizing a single metric.

Re: Taming Go’s memory usage, or how we avoided rewriting our client in Rust

#115
post #84

Earlier quoted context omitted.

Reflection is also typically needed for anything that needs to be generic over types. For example, if you want to write a function that can traverse or transform a map or slice, where the actual types aren't known at compile time. We have a lot of this in our Go code at the company I work for. I'm really looking forward to generics, which will help us rip out a ton of reflect calls.

That kind of code is generally non-idiomatic in Go. An experienced Go programmer looks at something that is generic over types and does something interesting and instinctively asks "what gives, where are the dead rabbits?". I'm less excited about generics. There's a cognitive cost to them, and the constraint current Go has against writing type-generic code is often very useful, the same way a word count limit is usef…

This argument is getting a little tiresome though, isn't it? It isn't simply enough to call something "non-idiomatic" to gloss over a deficiency. There's a cognitive cost to all language features, but most other general purpose statically typed programming languages seem to have come to the conclusion that the benefit outweighs the cost for some form of generics.

I am by no means a Go basher, it is one of my favorite languages. But I eagerly await generics.

Re: Taming Go’s memory usage, or how we avoided rewriting our client in Rust

#116
post #84

Earlier quoted context omitted.

That kind of code is generally non-idiomatic in Go. An experienced Go programmer looks at something that is generic over types and does something interesting and instinctively asks "what gives, where are the dead rabbits?". I'm less excited about generics. There's a cognitive cost to them, and the constraint current Go has against writing type-generic code is often very useful, the same way a word count limit is usef…

I’m so conflicted on that point. I’ve been writing a high performance CRDT in rust for the last few months, and I’m leaning heavily on generics. For example, one of my types is a special b-tree for RLE data. (So each entry is a simple range of values). The b-tree is used in about 3-4 different contexts, each time with a different type parameter depending on what I need. Without genetics I’d need to either duplicate m…

If we can be at a place where reasonable people can disagree about generics, I'm super happy, and think we've moved the discourse forward. There are things I like about generics, particularly in Rust (I've had the displeasure of dealing with them in C++, too). They're just not an unalloyed good thing.

Re: Taming Go’s memory usage, or how we avoided rewriting our client in Rust

#117
post #84

Earlier quoted context omitted.

That kind of code is generally non-idiomatic in Go. An experienced Go programmer looks at something that is generic over types and does something interesting and instinctively asks "what gives, where are the dead rabbits?". I'm less excited about generics. There's a cognitive cost to them, and the constraint current Go has against writing type-generic code is often very useful, the same way a word count limit is usef…

This argument is getting a little tiresome though, isn't it? It isn't simply enough to call something "non-idiomatic" to gloss over a deficiency. There's a cognitive cost to all language features, but most other general purpose statically typed programming languages seem to have come to the conclusion that the benefit outweighs the cost for some form of generics. I am by no means a Go basher, it is one of my favorite…

I could have written this more clearly. The fact that things that are generic over types are non-idiomatic today in Go has nothing to do with whether the upcoming generics feature is good or bad. They're unrelated arguments.

The latter argument is subjective and you might easily disagree. The former argument, about experienced Go programmers being wary when an API is generic over types, is pretty close to an objective fact; it is a true statement about conventional Go code.

Re: Taming Go’s memory usage, or how we avoided rewriting our client in Rust

#118
post #10

Buried in here are great examples of why rewrites don’t help: “The module that does this inference was recompiling those regular expressions each time it was asked to do the work.” “The reason for the allocation was a buffer holding decompressed data, before feeding it to a parser. …the output of the decompression could be fed directly into the parser, without any extra buffer.” The problem here isn’t that the langua…

Right, but GC encourages you to not think about memory at all until the program starts tipping over and fixing the underlying cause of the leak now requires an architecture change because the "we hold onto everything" assumption got baked into the structure in 2 places that you know about and 5 that you don't. I don't miss the rote parts of manual memory management, but it had the enormously beneficial side effect of…

> Right, but GC encourages you to not think about memory at all

I’ve come to a new obvious realisation with this sort of thing recently: if you care about some metric, make a test for it early and run it often.

If you care about correctness, grow unit tests and run them at least every commit.

If you care about performance, write a benchmark and run it often. You’ll start noticing what makes performance improve and regress, which over time improves your instincts. And you’ll start finding it upsetting when a small change drops performance by a few percent.

If you care about memory usage, do the same thing. Make a standard test suite and measure it regularly. Ideally write the test as early as possible in the development process. Doing things in a sloppy way will start feeling upsetting when it makes the metric get worse.

I find when I have a clear metric, it always feels great when I can make the numbers improve. And that in turn makes it really effortless bring my attention to performance work.

Re: Taming Go’s memory usage, or how we avoided rewriting our client in Rust

#119

After using Rust for a few years professionally it's my take that people that really want to use it haven't had much experience with it on real world projects. It just doesn't live up to the hype that surrounds it. The memory and CPU savings are negligible between Go and Rust in practice no matter what people might claim in theory. However, the side effects of making your team less productive by using Rust is a much…

Can you name some non-obvious problems?

Re: Taming Go’s memory usage, or how we avoided rewriting our client in Rust

#120
post #101
post #87

Earlier quoted context omitted.

To be fair, that is now the common "I rewrote X in Y" theme, which followed upon the Y ∈ { Ruby, Clojure, Scala, Kotlin,.... } from previous years.

And Go too! It's always fun to see posts from around 2014/2015 complaining about how every submission to Hacker News is now "I wrote X in Go", while now Go is the boring stuff and Rust is the hot new thing. I wonder what will be the next Rust though.

Some GC based language with dependent types.
Post reply on HN