Chiming in here in relative ignorance…
Offhand, it seems to me that the advantage to placing strings last is that you can buffer them in another segment making a single pass over the struct array and then appending them without a second touch. It plays fairly nicely with the cache, and writev() becomes your friend when the time comes to do your I/O.
Offhand, it seems to me that you could equally well buffer the structs, but it depends on the on-wire representation for references.
Logical truncate and physical truncate are two different things. I’d have to look at the wire representation to be sure, but I suspect it’s okay to truncate an already buffered array in the sense that the recipient will not be told about the (now garbage) extra bytes. Not efficient from a transmission perspective, and I can’t think of a good use case.
Kevin: I have two ignorant design questions here:
1. Given that messages are already divided into segments, did you consider an on-wire representation for references taking the form segment::offset coupled with an in-memory segment table somewhere? I expect you did, and I’m wondering what the issues are/were? Wide adoption of writev() is relatively recent, which seems relevant here, but using a byte offset on the wire precludes both out-of-order segment serialization and out-of order segment writes.
2. If there were a reason to, does the current API expose the on-wire reference representation? Is the current representation effectively part of the API?
Jonathan