Live data from Hacker News

Fivefold Slower Compared to Go? Optimizing Rust's Protobuf Decoding Performance

greptime.com

51–60 of 63 posts

Re: Fivefold Slower Compared to Go? Optimizing Rust's Protobuf Decoding Performance

#51
post #26
post #20

Earlier quoted context omitted.

It's technically `safe` as long as you never access the decoded struct once the original bytes is dropped. I believe that how `unsafe` works, the programmer, instead of compiler, ensures safety.

Yes, but their code appears to actually be `unsafe` (in the Rust terminology sense) without specifying that in their function declarations. They use `unsafe` inside their `slice` function, but return a value that is unsafe to use, hence `slice` should be marked `unsafe`, as should `copy_to_bytes` and then `merge_bytes`. Same for PromLabel::merge_field and PromTimeSeries::merge_field as far as I can see, and maybe hig…

I was looking at the main branch, and described the situation there. They have a different branch for the optimization work; in that branch, they do mark those functions as `unsafe` (and already did when I posted).

Re: Fivefold Slower Compared to Go? Optimizing Rust's Protobuf Decoding Performance

#52
post #39

Earlier quoted context omitted.

To bring this discussion back to earth, the Go code in question is: https://github.com/VictoriaMetrics/easyproto/blob/master/rea... I don't see why did you label Aliaksandr Valialkin, the author, an "expert". I mean, he's no dummy but what exactly makes him an expert on optimizing Go code? As someone who also writes Go, I don't see any "hyper optimizations" in the code. It just decodes the bytes of Protocol Buffer us…

> I don't see why did you label Aliaksandr Valialkin, the author, an "expert". I mean, he's no dummy but what exactly makes him an expert on optimizing Go code? I was trying to convey the meaning of "far more experienced than the blog post authors", but without having to insult the authors. It's a good writeup after all, and I'm glad they took the time. We must have some different interpretations of what "optimized"…

I'm not sure the presence of bit unpacking code in a decoder for a bit packed protocol is sufficient to call it hyper optimized. That seems like the nature of the problem.

Re: Fivefold Slower Compared to Go? Optimizing Rust's Protobuf Decoding Performance

#53

So in this case, with some modest performance engineering, Golang is surprisingly fast out of the box, and Rust requires more effort and increasingly less idiomatic code to reach the same result. Is this typical?

I haven't dug into the code, but it's clear that the Golang library has had a ton of optimization work put into it by very knowledgeable people. Techniques like object pooling are highly error prone, and certainly not "out of the box" Golang. The Rust code and the blog post, on the other hand, seem to be written by someone less familiar with Rust and high-performance parsing. I think they would have avoided all their…

> Techniques like object pooling are highly error prone, and certainly not "out of the box" Golang.

This one is actually out of the box in Golang, it's called sync.Pool and is accessible in the standard library. It's very easy to use and not error prone, I've used it many times without any issues.

But creator of VictoriaMetrics is indeed someone very knowledgeable and known in Golang community in context of optimization.

Re: Fivefold Slower Compared to Go? Optimizing Rust's Protobuf Decoding Performance

#54
post #39

Earlier quoted context omitted.

To bring this discussion back to earth, the Go code in question is: https://github.com/VictoriaMetrics/easyproto/blob/master/rea... I don't see why did you label Aliaksandr Valialkin, the author, an "expert". I mean, he's no dummy but what exactly makes him an expert on optimizing Go code? As someone who also writes Go, I don't see any "hyper optimizations" in the code. It just decodes the bytes of Protocol Buffer us…

> I don't see why did you label Aliaksandr Valialkin, the author, an "expert". I mean, he's no dummy but what exactly makes him an expert on optimizing Go code? I was trying to convey the meaning of "far more experienced than the blog post authors", but without having to insult the authors. It's a good writeup after all, and I'm glad they took the time. We must have some different interpretations of what "optimized"…

Protobuf uses a bunch of variable length encodings. Here it's decoding a TLV format, but the length is itself a variable length integer (and seems to be a kind of tag-value encoding?) where you basically get 7 bits per byte telling you the value, and the leftmost bit tells you whether there's another byte. So if you mask with 0x8080 and get zero, then it was a 1 byte (7 bit) integer.

If 0x8080 is not set, then the tag-value record is 2 bytes. Left byte has tag. Right is value. Then they're masking with 0x0700 to get the type of record, which should be LEN.

So if it's a single byte LEN record, they can take that single byte as the length (they mask with 0x00ff, but really it's 0x007f. They already know the 0x80 bit is zero, and the value is contained in the least significant 7 bits). Otherwise they have to do some fiddly logic to decode the variable length integer to figure out the length (length here being the L in TLV).

Re: Fivefold Slower Compared to Go? Optimizing Rust's Protobuf Decoding Performance

#55

So in this case, with some modest performance engineering, Golang is surprisingly fast out of the box, and Rust requires more effort and increasingly less idiomatic code to reach the same result. Is this typical?

More or less.

For a language designed for fresh-out-of-college engineer to pick up in a few weeks and be effective, it is very easy to squeeze out a lot of performance.

* built-in profiler. * built-in escape analysis tool. * It's easy to pass pointers instead of copying data. * []byte is sub-slice-able, with a backing array. This does throw people off occasionally, but the trade off is performance. * Go lets you have real arrays of structs, optimizing cpu caches. * Built-in memory pools

And more.

And if you look at "non-idiomatic" performance code, they are surprisingly legible by the said fresh engineer. It's as if the designers didn't want to give up all the usual C performance tricks while making a Java/Python kind of friendly language, and this shows.

Of course Go can go only so far, due to the built-in runtime and GC. But it gets very far. Much farther than at first glance, or second glances that language snobs would give credit for.

Re: Fivefold Slower Compared to Go? Optimizing Rust's Protobuf Decoding Performance

#56

So in this case, with some modest performance engineering, Golang is surprisingly fast out of the box, and Rust requires more effort and increasingly less idiomatic code to reach the same result. Is this typical?

While it’s a nice bed time story if you like go, the reality is no, it’s not typical. Go has a good perf story, but typically rust or c++ would be faster after heavy optimisation; and should be more or less on par with typical applications. This isn’t a critique of go, and shouldn’t surprise anyone. Typically go also has unexpected optimisation hoops to jump through and problems related to the heavy use of channels (…

It's really easy to improve the performance of Go implementation as compared to python or Java. There are lots of built-in tools to help you (like the profiler), and the resulting code is really very legible even to fresh college grads.

This is based on my first hand experience, but YMMV.

Re: Fivefold Slower Compared to Go? Optimizing Rust's Protobuf Decoding Performance

#57
The benchmark is not comparing apples to apples.

prost is the most widely used Protobuf implementation in Rust, maintained by the Tokio organization. prost generates structs and serialization/deserialization code for you.

easyproto according to GitHib Search is used only by two projects. easyproto provides primitives for serializing and deserializing Protobuf, and requires hand writing code to do both.

A fair comparison would be prost vs google.golang.org/protobuf, or easyproto vs parts of quick-protobuf.

In most cases you can make Go as fast as Rust, but from my experience writing performance-sensitive code in Go requires significantly larger time investment and overall requires deeper language expertise. Pebble (RocksDB replacement in Go by CockroachDB) is a good example of this, the codebase is littered with hand-inlined[1] functions, hand-unrolled loops and it's not[2] even using Go memory management for performance critical parts, it's using the C memory allocator and manual memory management.

[prost]: https://github.com/tokio-rs/prost [easyproto]: https://github.com/VictoriaMetrics/easyproto [google.golang.org/protobuf]: https://github.com/protocolbuffers/protobuf-go [quick-protobuf]: https://github.com/tafia/quick-protobuf [1]: https://github.com/cockroachdb/pebble/blob/c34894c46703fd823... [2]: https://github.com/cockroachdb/pebble/blob/master/docs/memor...

Re: Fivefold Slower Compared to Go? Optimizing Rust's Protobuf Decoding Performance

#58
post #2

In the image at the top of the article, why is the Rust crab altered to have "angry" eyes and holding a knife aimed at the Go gopher? Aside from the joke of "don't bring a knife to a protobuf fight" the inference of violence sucks and lessens the spirit of friendly competition and "all in good fun." I don't know if Rust has a code-of-conduct or rules for use of their mascot, but I bet this doesn't follow it.

Congratulations! You've won the Poe's Law Post of the Day Award! "Poe's law is an adage of Internet culture which says that, without a clear indicator of the author's intent, any parodic or sarcastic expression of extreme views can be mistaken by some readers for a sincere expression of those views." https://en.m.wikipedia.org/wiki/Poe's_law

But it does appear to be the author's intent, considering their Twitter account has a photo of the crab using the gohper's carcass (with dead eyes) as a carpet referencing the same article (if you translate the Chinese). Also, the author went out of their way to use a CrabLang logo (not a Rust logo) to add the knife. https://x.com/ratuthomm/status/1775183479858483439 https://imgur.com/a/txMb4Kw

Re: Fivefold Slower Compared to Go? Optimizing Rust's Protobuf Decoding Performance

#59

Earlier quoted context omitted.

I don't think I understand the comparison. Can you think of another one that involves a weapon and directed violence?

It’s simple. You ignore fire as a bad thing and don’t even consider that as equivalent comparison to a knife. But someone who was affected by arson probably will say “why include fire in a blog post?!” . My point is, it is not on the author to think about all these effect when they write/speak. As a mature society, we should learn to not expect every source to filter their thoughts and rather expect the consumer to f…

Thanks for engaging, but I don't think I follow you. Can you think of another example that specifically involves a weapon and directed violence?

Re: Fivefold Slower Compared to Go? Optimizing Rust's Protobuf Decoding Performance

#60

Earlier quoted context omitted.

Congratulations! You've won the Poe's Law Post of the Day Award! "Poe's law is an adage of Internet culture which says that, without a clear indicator of the author's intent, any parodic or sarcastic expression of extreme views can be mistaken by some readers for a sincere expression of those views." https://en.m.wikipedia.org/wiki/Poe's_law

But it does appear to be the author's intent, considering their Twitter account has a photo of the crab using the gohper's carcass (with dead eyes) as a carpet referencing the same article (if you translate the Chinese). Also, the author went out of their way to use a CrabLang logo (not a Rust logo) to add the knife. https://x.com/ratuthomm/status/1775183479858483439 https://imgur.com/a/txMb4Kw

[deleted]
Post reply on HN