4 ms·
It's also likely faster to parse; string and array sizes are statically known, and all parsing happens in order, so there's no backtracking. Want to parse a str
by lalaithion 7y ago
It's also likely faster to parse; string and array sizes are statically known, and all parsing happens in order, so there's no backtracking. Want to parse a string in JSON? okay, this is a starting quote, so let's iterate down the rest of the document, looking for unescaped end quotes, and then copy that into a buffer. In msgpack, it's a single memcpy. Additionally, with number heavy messages, then it shines.
{"red": 127,"green": 28,"blue": 27,"x": -18,"y": 27,"z": 2008,"time": 1583862185,"dollars": 1298,"cents":12,"name":"tom",timeseries":[1,2,3,4,55,66,77,218,239,340,9009,80008,400004]}
gives 106 bytes with msgpack and 157 with gzip. Also, if you gzip the msgpack, for your message example, it's 248 bytes.
- cptwunderlich 7y agoAnd you trust a message from an unknown source? You can't simply memcpy according to some length indicator, that's just not safe. You still have to parse and validate.
- kingofpandora 7y agoGenuine question - is it dangerous to memcpy X bytes that we know must be interpreted as, say, an integer?
- deleted 7y ago[deleted]
- tangent128 7y agoPotentially. Most network protocols are big-endian while x86 is little-endian.
- byte1918 7y agoNo. Everything is 0s and 1s after all. Take for eg. a byte. It has 8 bits and by permutating all the 0s and 1s you end up with all the possible values of a signed byte; all the numbers -128 to 127. So now, if you were to copy a byte from a random memory location that byte will just contain a permutation of 0s and 1s which when interpreted as a signed int, will simply contain a number between -128 and 127.
- kingofpandora 7y agoThat's what I thought ...
- bmn__ 7y agohttps://capnproto.org https://capnproto.org serialisation scheme skips the decoding. Does that make it not safe?
- tebeka 7y agoNo serizalization is safe - https://docs.microsoft.com/en-us/security-updates/securitybulletins/2004/ms04-028 https://docs.microsoft.com/en-us/security-updates/securitybu... - https://en.wikipedia.org/wiki/Billion_laughs_attack https://en.wikipedia.org/wiki/Billion_laughs_attack - https://en.wikipedia.org/wiki/Zip_bomb https://en.wikipedia.org/wiki/Zip_bomb - ...
- strbean 7y agoNone of those are serialization schemes. XML can be used for serialization, but if you look at the whole ecosystem it is a Turing-complete complexity monster, so of course it isn't safe.
- DougBTX 7y agoIt depends on what constraints apply to the data. Any bit pattern could be used for an int, but to guarantee a UTF-8 string it would need to be validated.
- lwf 7y agoAs long as you know the length of the entire buffer, you just ensure that: current_addr + message_len - start_addr < buffer_len Or am I missing something?
- diabeetusman 7y agobuffer_len could be larger than the message, copying some incorrect things into memory. Similar to HeartBleed, where there wasn't validation on the heartbeat message, and the server would echo back buffer_len instead of just what was sent.
- theamk 7y agoI believe author intended buffer_len to be the length of incoming buffer (size of HTTP payload, number of bytes read from file, length of the database entry, etc...). So the worst that can happen is that entire input message is consumed -- like a JS payload which missed closing quote. I can think of a very contrived situation where this can be a problem, but in most cases this will be perfectly safe.
- maxwindiff 7y agoInvalid unicode sequences?
- kentonv 7y agoObviously you need to check that the length doesn't go past the end of the message, but that's a trivial O(1) check. You don't have to scan the bytes of the string first to decide if they are safe to memcpy.
- laumars 7y agoYou might want to validate those byte sequences are valid character encodings.
- kelnos 7y agoYou should be doing that with JSON as well, so this isn't a pro/con of either format.
- laumars 7y agoThat was obviously my point. ie just because MessagePack is a binary format it doesn't mean you can skip the same string checks that JSON requires; which means parsing MessagePack strings is unlikely to be any faster than JSON strings (contrary to the suggestions others have implied with the "just memcpy" comments). It's just with JSON that validation is done as part of the parser (remember JSON only technically supports a subset of ASCII and any extended characters or unicode is encoded via escape codes) where as with MessagePack you'd need to do that validation as an additional step. Integers, on the hand, might differ since JSON would need additional validation (again, backed into the parser) which MessagePack would not because MessagePack encodes the integers as binary integers where as JSON encodes them as ASCII values that would need converting back to binary integers. (hint: read the message I'm replying to).
- kentonv 7y agoMany (most?) applications do not actually care whether a byte blob of text is structurally valid UTF-8. They are either passing it around as an opaque byte blob, or already applying much stricter application-specific validation. Validating UTF-8 automatically at the serialization layer is a huge waste of cycles, especially in a big distributed system.
- hinkley 7y agoKeep fighting the good fight.
- rumanator 7y ago> Want to parse a string in JSON? okay, this is a starting quote, so let's iterate down the rest of the document, looking for unescaped end quotes, and then copy that into a buffer. Yes, so what's the problem? Meanwhile keep in mind that the JSON document was already passed in a HTTP request body, or that its trivial to put string length checks on a parser, or even nesting limit checks.
- hn_throwaway_99 7y agoDelimited formats are, in general, slower to parse than formats where the record sizes are encoded in the message. That said, not something I want to prematurely optimize for.
- strbean 7y agoI don't think it's that premature. Making the (big) assumption that serialization format X has good stable support in your language, and has the same expressive capabilities as JSON, you should be able to use it as a drop in replacement (as long as you control both ends of the communication...). And doesn't a huge portion of what we do around here amount to "shuffle serialized data around as efficiently as we can"?
- rumanator 7y ago> Delimited formats are, in general, slower to parse than formats where the record sizes are encoded in the message. I don't see your point at all. The state machine required to parse a JSON string essentially has only 2 states: current token is either a string character or a string delimiter. That's it. Adding a record size increases the number of states because now you not only need to track if a token is a string character but also if the character makes sense to be there within that state. Moreover, when you parse a JSON string, once you hit the string's end delimiter you already are able to calculate the string size. Thus, if the string is short enough to fit the buffer then not only is the lexer simpler but it also requires the same memory allocations than strig formats with record sizes. If however a string doesn't fit the buffer then we are already in the territory of a ropes data structure in both cases, thus the number of memory allocations tend to be equivalent.