mirror of
https://github.com/nlohmann/json.git
synced 2026-10-15 02:37:13 +00:00
The sizes of a run of integers are hard to predict, and so is the type of each element in an array that mixes negative (number_integer) and non-negative (number_unsigned) values. Writing an integer branched on the type, the sign, and the 1/2/4/8-byte size class, and the mispredictions were the larger part of the time left on integer arrays. - number_integer and number_unsigned share one case of write_cbor; the major type and the argument are selected with a sign mask. - An integer's head is assembled without branches: the size class comes from a table indexed by count_leading_zeros(), and the first byte and the argument in network order are stored as one byte and one 8-byte word, of which only the head's length is kept. Heads of strings and containers keep the branching write_cbor_head(), as their lengths are mostly predictable. - Arrays are written by write_cbor_array(), kept out of line so that the registers its loop needs are not saved on every call of write_cbor. Runs of integers are encoded straight into space reserved from the sink (the new reserve()/commit() of both sinks), so the write pointer stays in a register instead of being reloaded for every value. The output is unchanged; the new test compares integer arrays at every head-size boundary, in runs shorter and longer than one reservation and broken up by other values, with an independent encoder through each sink. Signed-off-by: Niels Lohmann <mail@nlohmann.me>