Hacker News new | ask | show | jobs
by anon291 721 days ago
Depending on the use case, it's often better to just copy structs directly, with maybe some care for endianness (little-endian). But at this point, the two most popular platforms, ARM and x86, agree on endianness and most alignment.

There's almost no reason why RPC should not just be

  send(sk, (void *)&mystruct, sizeof(struct mystructtype), 0)
3 comments

Do all of your platforms have the same word width? The same -fshort-enums settings? Do you know that none of your data structures include pointers? Do all of your systems use the same compiler? Compiler version?

I agree it will usually work, but this becomes an ABI concern, and it's surprisingly common to have ABI mismatches on one platform with the items I've noted above.

I've seen wire protocols that had junk for the alignment buffering in such structs. And I've seen people have to do a whole lot of work to make the wire protocol work on a newer compiler/platform. Also, the whole point of a network protocol being documented is that it decouples the interface (msgs over a network) from the implementation (parsing and acting on msgs). Your v1 server might be able to just copy the read buffer into a struct, but your v2 server won't. And it is possible and desirable to live in a world where you can change your implementation but leave your interface alone (although some parts of the software ecosystem seem to not know this nice fact and implicitly fight against realizing it).

My issue with gRPC is simple, the Go gRPC server code does a lot of allocations. I have a gRPC service where each container does 50-80K/second of incoming calls and I spend a ton of time in GC and in allocating headers for all the msgs. I have a similar REST service where I use fasthttp with 0 allocs (but all the stupidly high number of connections due to the lack of multiplexing thru the connection).

Go's GC wasn't really made with throughput maximization in mind. It's a language that doesn't scale that well to take advantage of beefy nodes and has weak compiler. I suppose the Google's vision for it is to "crank the replica count up". gRPC servers based on top of ASP.NET Core, Java Vert.X and Rust Thruster will provide you with much higher throughput on multi-core nodes.

https://github.com/LesnyRumcajs/grpc_bench/discussions/441

Ignoring the incompatibilities in word size, endianness, etc, how does a Go or JavaScript or etc program on the receiving end know what `mystruct` is? What if you want to send string, list, map, etc data?
string, list, map, etc? You have to use an encoding scheme.

As for go / javascript? I think most languages have the ability to inspect a raw buffer.

> string, list, map, etc? You have to use an encoding scheme.

Yes, you have to use an encoding scheme like JSON or Protobufs. Dumping memory directly down the pipe as you're suggesting doesn't work.

> As for go / javascript? I think most languages have the ability to inspect a raw buffer.

No language has the ability to read a raw buffer and know what the contents are supposed to mean. There needs to be a protocol for decoding the data, for example JSON or Protobufs.

Won't work if your struct has any pointers in it.
I'd recommend not doing that then. Of course the same is true if you coerce a pointer to an int64 and store it in a protobuf.
It's not the pointers themselves so much as what they're typically used for. How would you do dynamic sizing? Imagine sending just a struct of integer arrays this way, you'd have to either know their sizes ahead of time or just be ok with sending a lot of empty bits up to some max size. And recursive structures would be impossible.

You could get around this with a ton of effort around serdes, but it'd amount to reinventing ASN1 or Protobuf.

A lot of protocols in low latency trading systems just have fixed maximum size strings and will right pad with NUL or ASCII space characters.

Packed structs with fixed size fields, little endian integers and fixed point is heaven to work with.

I can see that in niche situations, particularly if you have a flat structure and uniform hardware. Cap'n Proto is also a way to do zero-parsing, but it has other costs.