Live data from Hacker News

Replacing Protobuf with Rust

pgdog.dev

81–90 of 135 posts

Re: Replacing Protobuf with Rust

#81
post #56

Earlier quoted context omitted.

Protobuf does something important that copying memory cannot do: a protocol that can be changed separately on either end and things can still work. You have to build for "my client doesn't send some new data" (make a good default), or "I got extra data I don't understand" (ignore it). However the ability to upgrade part of the system is critical when the system is large and complex since you can't fix everything to u…

But something more modern that doesn’t have the encoding/decoding penalty of Protobuf would be better (eg cap’n’proto but there’s a bunch now in this space).

Not that you are wrong, but in the real world this is not significant for most uses. If it is significant you are doing too much IPC. Or maybe using protobuf where you should be making a direct function call. Fix the architecture either way. (similar to how I can make bubble sort faster with careful machine code optimization, but it is hard to make modern tim sort slower in the real world no matter how bad the implementation is)

Re: Replacing Protobuf with Rust

#82
post #79
post #57

What I find particularly ironic is that the title make it feel like Rust gives a 5x performance improvement when it actually slows thing down. The problem they have software written in Rust, and they need to use the libpg_query library, that is written in C. Because they can't use the C library directly, they had to use a Rust-to-C binding library, that uses Protobuf for portability reasons. Problem is that it is slo…

Given they heavily used LLMs for this optimization, makes you wonder why they didn’t use them to just port the C library to rust entirely. I think the volume of library ports to more languages/the most performant languages is going to explode, especially given it’s a relatively deterministic effort so long as you have good tests and api contracts, etc

The underlying C library interacts directly with the postgres query parser (therefore, Postgres source). So unless you rewrite postgres in Rust, you wouldn't be able to do that.

Re: Replacing Protobuf with Rust

#83
post #70
post #65

Earlier quoted context omitted.

That would make sense if protobuf was complex, bloated, slow. But it's not, so the question should be why not use it, unless you are doing browser stuff.

If you are going to use it elsewhere, why not use it for browser stuff too?

I would advise against it. Too much friction, try it, maybe you will have a different experience than mine.

Re: Replacing Protobuf with Rust

#84
post #32

I find the title a bit misleading. I think it should be titled It’s Faster to Copy Memory Directly than Send a Protobuf. Which then seems rather obvious that removing a serialization and deserialization step reduces runtime.

Why don't we use standardized zero-copy data formats for this kind of thing? A standardized layout like Arrow means that the data is not tied to the layout/padding of a particular language, potential security problems like bounds checks are automatically handled by the tooling, and it works well over multiple communication channels.

While Arrow is amazing, it is only the C Data Interface that can be FFI'ed, which is pretty low level. If you have something higher-level like a table or a vector of recordbatches, you have to write quite a bit of FFI glue yourself. It is still performant because it's a tiny amount of metadata, but it can still be a bit tedious.

And the reason is ABI compatibility. Reasoning about ABI compatibility across different C++ versions and optimization levels and architectures can be a nightmare, let alone different programming languages.

The reason it works at all for Arrow is that the leaf levels of the data model are large contiguous columnar arrays, so reconstructing the higher layers still gets you a lot of value. The other domains where it works are tensors/DLPack and scientific arrays (Zarr etc). For arbitrary struct layouts across languages/architectures/versions, serdes is way more reliable than a universal ABI.

Re: Replacing Protobuf with Rust

#85
Gotta say, I love using PGDog. It has some fantastic built in features, and I'm looking forward to testing out the improved query parser. Lev and the team are heroes.

At the scale we were using PGDog, enabling the previous form of the query parser was extremely expensive (we would have had to 16x our pgdog fleet size).

Re: Replacing Protobuf with Rust

#86
post #57

What I find particularly ironic is that the title make it feel like Rust gives a 5x performance improvement when it actually slows thing down. The problem they have software written in Rust, and they need to use the libpg_query library, that is written in C. Because they can't use the C library directly, they had to use a Rust-to-C binding library, that uses Protobuf for portability reasons. Problem is that it is slo…

>> But had they written their software in C, they wouldn't have needed to do any conversion at all. It means they could have titled the article "How we lowered the performance penalty of using Rust". That's not really fair. The library was doing serialization/deserialization which was poor design choice from a performance perspective. They just made a more sane API that doesn't do all that extra work. It might best b…

Because then they never would have needed the poorly-designed intermediate library.

Re: Replacing Protobuf with Rust

#87
post #69
post #68

Earlier quoted context omitted.

>Protobuf sounds like the wrong too This sort of use for proto is quite common at google

No it’s not common for two pieces of code within a single process to communicate by serializing the protobuf into the wire format and deserializing it. It’s however somewhat common to pass in-memory protobuf objects between code, because the author didn’t want to define a custom struct but preferred to use an existing protobuf definition.

I agree it's not super common, but Boq's in-process RPC feature encourages this pattern.

Re: Replacing Protobuf with Rust

#88
post #57

What I find particularly ironic is that the title make it feel like Rust gives a 5x performance improvement when it actually slows thing down. The problem they have software written in Rust, and they need to use the libpg_query library, that is written in C. Because they can't use the C library directly, they had to use a Rust-to-C binding library, that uses Protobuf for portability reasons. Problem is that it is slo…

>> But had they written their software in C, they wouldn't have needed to do any conversion at all. It means they could have titled the article "How we lowered the performance penalty of using Rust". That's not really fair. The library was doing serialization/deserialization which was poor design choice from a performance perspective. They just made a more sane API that doesn't do all that extra work. It might best b…

> BTW what makes you think writing their end in C would yield even higher performance?

C is not inherently faster, you are right about that.

But what I understand is that the library they use works with data structures that are designed to be used in a C-like language, and are presumably full of raw pointers. These are not ideal for working in Rust, instead, presumably, they wrote their own data model in Rust fashion, which means that now, they need to make a conversion, which is obviously slower than doing nothing.

They probably could have worked with the C structures directly, resulting in code that could be as fast as C, but that wouldn't make for great Rust code. In the end, they chose the compromise of speeding up conversion.

Also, the use of Protobuf may be a poor choice from a performance perspective, but it is a good choice for portability, it allows them to support plenty of languages for cheaper, and Rust was just one among others. The PgDog team gave Rust and their specific application special treatment.

Re: Replacing Protobuf with Rust

#89
post #83
post #70

Earlier quoted context omitted.

If you are going to use it elsewhere, why not use it for browser stuff too?

I would advise against it. Too much friction, try it, maybe you will have a different experience than mine.

I am curious about what kind of friction you encountered. Were you generating ad-hoc protobuf messages?

Assuming you were using Protobufs as they are usually used, meaning under generated code, I saw no difference between using it in Javascript and any other language in my experience. The wire format is beyond your concern. At least it is no more of your concern than it is in any other environment.

There are a number of different generator implementations for Javascript/Typescript. Some of them have some peculiar design choices. Is that where you found issue? I would certainly agree with that, but others aren't so bad. That doesn't really have anything to do with the browser, though. You'd have the same problem using protobufs under Node.js.

Post reply on HN