Ok, so I promised some updated stats following the wire deserialize optimization. This was not a huge amount of work, and not terribly complex, but a lot of details to get right and tested. In all it took a calendar week.
The optimization consists of a block_view that contains a tx_view for each tx, contained within the network block message type, in place of the chain::block. The block view contains the socket buffer, which is the wire block. The view provides quick access to data within the buffer required for hashes and identity validation (merkle root and witness commitment), as well as access for store serialization. The block message still provides access to the chain::block by on-demand deserialization from the buffer, though that's not currently used.
This eliminates the population of a chain::block object for the purpose of reading from the wire and writing to the store. The chain objects are really for validation, and we only validate what is read from the store, not from the wire. From the wire we just need identity, which is much simpler and provided by the views. This is a big optimization in that it prevents the computation and memory allocation for construction and destruction of the block, which can have many tens of thousands of sub-objects. We previously optimized that using the linear memory allocator, reducing the construction down to one allocation. But this significantly over allocates the block on average, and the block itself averages 5-10x the memory of the buffer it is constructed from (in one case 20x).