Live data from Hacker News

Don't Use Protobuf for Telemetry

richardstartin.github.io

51–60 of 195 posts

Re: Don't Use Protobuf for Telemetry

#51

Earlier quoted context omitted.

Signal boosting this. I am the last person to be swayed by “use our magical design that solves all problems,” but in the case of protobufs, it solves most of them. I didn’t like it until I was forced to use it. Now I’m not sure I’ll ever go back. There’s a handy code snippet to turn any protobuf message into JSON: from google.protobuf.json_format import MessageToJson import json from pprint import pprint as pp pp(jso…

Why they use Java like code in Python? "MessageToJson" doesn't look idiomatic.

This is because this follows Google’s internal Python styeguide, which was established well before PEP8 and even Python 2.x.

Re: Don't Use Protobuf for Telemetry

#52

Earlier quoted context omitted.

CP was written by Kenton Varda, who spent many years working on protobuf at Google. One massive advantage of protobuf for mainstream Google languages (C++, Java) is that Google has used them extremely heavily for many years, and you can trust that they've been extensively battle tested in Google's enormous high-traffic services, and scrutinized by Google's vast army of engineers. Kenton's experience notwithstanding,…

Part of the reason that Kenton left Google and created CapnProto, was because he was the only person working on proto at Google trying to fix the problems Google found.

That's not really accurate... I transferred off the Protobuf project three years before quitting Google, based on feedback I received from management suggesting they didn't think my work there was worthwhile. By the time I left Google, there was a new team maintaining Protobuf, and my reasons for leaving were not related to Protobuf.

I didn't leave Google to create Cap'n Proto. Rather, having left Google and being free to do whatever I wanted for a while, I created Cap'n Proto mostly for fun, to "scratch an itch" by trying out a different design.

Re: Don't Use Protobuf for Telemetry

#53
post #31

I have written an in-house implementation of protobuf for C++ (sorry can't share) and studied the wire format extensively. Google's implementations, at least C++ and Java, are a bunch of bloated crap (or maybe they're very good, but for a use case that I haven't yet encountered). Don't shoot down the format because of a specific implementation, find or write a better one and enjoy the fact that every language has at…

> Google's implementations, at least C++ and Java, are a bunch of bloated crap (or maybe they're very good, but for a use case that I haven't yet encountered).

As someone who has been working on protobuf-related things for >10 years, including creating a size-focused implementation (https://github.com/protocolbuffers/upb), and has been working on the protobuf team for >5 years, I have a few thoughts on this (thoughts are my own, and I don't speak for anybody else).

I think it is true that protobuf C++ could be a lot more lean than it currently is (I can't speak to Java as I don't work on it directly). That's why I created upb to begin with. But there's also a bit more to this story.

The protobuf core runtime is split into two parts, "lite" and "full". If you don't need reflection for your protos, it's better to use "lite" by using "option optimize_for = LITE_RUNTIME" in your .proto file (https://developers.google.com/protocol-buffers/docs/proto#op...). That will cut out a huge amount of code size from your binary. On the downside, you won't get functionality that requires reflection, such as text format, JSON, and DebugString().

Even the lite runtime can get "lighter" if you compile your binary to statically link the runtime and strip unused symbols with -ffunction-sections/-fdata-sections/--gc-sections flags. Some parts of the lite runtime are only needed in unusual situations, like ExtensionSet which is only used if your protos use proto2 extensions (https://developers.google.com/protocol-buffers/docs/proto#ex...). If you avoid these cases, the lite runtime is quite light.

However, there is also the issue of the generated code size. Unlike the runtime, this is not a fixed cost, but is proportional to the number of messages you use. If you have a lot of messages it can quickly dwarf the size of the runtime. For this reason, C++ also supports "option optimize_for = CODE_SIZE" which uses reflection-based algorithms for all parsing/serialization/etc instead of using generated code. This means you pay the fixed size hit from linking in the full runtime, but the generated code size is much smaller. On the downside, "optimize_for = CODE_SIZE" has a severe ~10x speed penalty for parsing and serialization.

I have long had the goal of making https://github.com/protocolbuffers/upb competitive with protobuf C++ in speed while achieving much smaller code size. With the benefit of 10 years of hindsight and many wrong turns, upb is beginning to meet and even surpass these goals. It is an order of magnitude smaller than protobuf C++, both in the core runtime and the generated code, and after some recent experiments it is beginning to significantly surpass it in speed also (I want to publish these results soon, but the code was merged in this PR: https://github.com/protocolbuffers/upb/pull/310).

upb has downsides that prevent it from being fully "user ready" yet: the API is still not 100% stable, there is no C++ API for the generated code yet (and C APIs for protobuf are relatively verbose and painful), it has a bunch of legacy APIs sitting around that I am just on the verge of being able to finally delete, and it doesn't support proto2 extensions yet. On the upside, upb is 100% conformant on every other protobuf feature, it supports reflection, JSON, and text format, but also lets you omit these if you don't want to pay the code size.

I hope 2021 is a year when I'll be able to publish more about these results, and when upb will be a more viable choice for users who want a smaller protobuf implementation.

Re: Don't Use Protobuf for Telemetry

#54
post #31

I have written an in-house implementation of protobuf for C++ (sorry can't share) and studied the wire format extensively. Google's implementations, at least C++ and Java, are a bunch of bloated crap (or maybe they're very good, but for a use case that I haven't yet encountered). Don't shoot down the format because of a specific implementation, find or write a better one and enjoy the fact that every language has at…

Mind elaborating on how the "standard" C++ and Java protobuf implementations are bloated? [edit] I'm genuinely asking. I'm guessing you mean in the generated APIs, i.e. the code "weight", but maybe you meant something else?

Things may have improved since, but the implementations are somehow very large and slow.

Things may have changed since, but AFAIK the C++ implementation would always allocate on the heap for nested messages, and perhaps even for optional scalars. This may be optimal for larger documents, but not for smallish messages (my use case was market data and trading instructions). I measured certain small messages, where an encode/decode pair would take over a microsecond with Google's implementation, but about 50 ns with a simpler one (versus 15 ns for a memcpy).

For Java my experience is mostly with the API itself, which felt very heavy.

Edit: I think a lot depends on your use case. I use protobuf mostly as a 'trusted' protocol. If someone didn't set a required field, I don't care. Some bloat may have to do with verifications that I've never needed.

Re: Don't Use Protobuf for Telemetry

#55
post #22
post #14

Google's own protobuf runtime is so bloated that even google themselves don't use it in many of their software, but rather nanopb[1], which is done by completely unrelated person to google. 1: https://jpa.kapsi.fi/nanopb/

I don’t think that’s true in google3. People often mistake the scale of Google’s internal code with respect to their visible external code.

For anyone unfamiliar, Google3 is apparently Google's monorepo, according to this HN comment:

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

Re: Don't Use Protobuf for Telemetry

#58
post #31

I have written an in-house implementation of protobuf for C++ (sorry can't share) and studied the wire format extensively. Google's implementations, at least C++ and Java, are a bunch of bloated crap (or maybe they're very good, but for a use case that I haven't yet encountered). Don't shoot down the format because of a specific implementation, find or write a better one and enjoy the fact that every language has at…

pb is also used in low-resource/embedded systems (to send the data to the servers). In these cases, the processors typically have little to no cache and very limited RAM, Performing multiple encoding passes is the only option and each pass is as expensive as the first.

In these environments you'd typically take special care to keep messages flat, I think - in which case there's no problem with multiple passes.

Re: Don't Use Protobuf for Telemetry

#59
post #33

Does anyone have an up-to date comparison protobuf vs captnproto instead? ( https://capnproto.org/ ) I am starting a new project and it looked really interesting, but I still have to read comments from people who used both in detail

CP was written by Kenton Varda, who spent many years working on protobuf at Google. One massive advantage of protobuf for mainstream Google languages (C++, Java) is that Google has used them extremely heavily for many years, and you can trust that they've been extensively battle tested in Google's enormous high-traffic services, and scrutinized by Google's vast army of engineers. Kenton's experience notwithstanding,…

Eh... I'd actually argue that Protobuf's big advantage is all the languages it supports that Cap'n Proto doesn't.

If you're using C++ exclusively, I'd argue Cap'n Proto beats Protobuf. That "army of engineers" isn't necessarily the advantage you think it is -- rather than forcing Protobuf to be the best it can be, I would argue they forced Protobuf to get stuck with early design decisions that no one thinks were ideal (e.g. varint encoding), because it's too hard to change once you have a lot of users. Battle-testing is great, but you could argue that Cap'n Proto benefited more from Protobuf's battle-testing than Protobuf itself did, since Cap'n Proto was designed from scratch with those lessons already learned.

On the other hand, if you need to support a broad set of languages, Protobuf is more likely to meet your needs. This is where the army of engineers and Google backing is helpful -- in building out support for a wide variety of languages and platforms.

Re: Don't Use Protobuf for Telemetry

#60
post #31

I have written an in-house implementation of protobuf for C++ (sorry can't share) and studied the wire format extensively. Google's implementations, at least C++ and Java, are a bunch of bloated crap (or maybe they're very good, but for a use case that I haven't yet encountered). Don't shoot down the format because of a specific implementation, find or write a better one and enjoy the fact that every language has at…

The author of this piece is wanting to stream possibly multi-MB messages with sub-linear memory use. See more in our Twitter conversation here: https://twitter.com/richardstartin/status/134406813297822105...

If you are expecting multi-MB messages protobuf isn't the best option as the author highlighted. Often you can combat this by breaking a large message into a stream of smaller messages but for larger amounts of data you will want something else.
Post reply on HN