You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We don't have any data about message's decompressed P2P payload size so when we decompress we have to assume the worst case and allocate some memory according to that which is quite expensive. Adding this size to the protocol either by switching to stream encoding or by an explicit field would allow for more optimal memory usage.
Current status
#710 has brought with it LZ4-compressed P2P message payloads so that if there is a flag set in the message the payload should be decompressed and it's being done with DecompressLz4 that looks like this:
var maxDecompressDataLength = data.Length * 255;
if (maxDecompressDataLength > 0) maxOutput = Math.Min(maxOutput, maxDecompressDataLength);
using var buffer = MemoryPool<byte>.Shared.Rent(maxOutput);
...
So it's allocating a space 255 times more than the incoming compressed payload (of course limited by PayloadMaxSize, but it's 32M which is quite a lot). It's obviously designed for the worst case lacking any real reference for the size, but these allocations seem to be wasteful as typical compression ratio is expected to be far lower than 255.
Proposed changes
There are two basic approaches to solving it:
using stream lz4 format with all of its magics and other metadata (and this
is the way it was originally implemented, see TCP P2P optimization #710 (comment)), this
will make decompression just work.
adding a field to _payload_compressed (or Message itself) that would
contain an uint32 with the size of uncompressed payload, this would require
using the data from this field when decompressing, but it's trivial to do
I have a slight preference for the first one, but at the same time it's perfectly fine to do the second.
Expected effect
Reducing memory pressure in typical usage scenarios. This doesn't prevent malicious node from specifying PayloadMaxSize for decompressed size in all of its messages, but it at the same time makes the node use less memory for regular communication which I think is beneficial.
Neo Version
Neo 3
Where in the software does this update applies to?
Summary
We don't have any data about message's decompressed P2P payload size so when we decompress we have to assume the worst case and allocate some memory according to that which is quite expensive. Adding this size to the protocol either by switching to stream encoding or by an explicit field would allow for more optimal memory usage.
Current status
#710 has brought with it LZ4-compressed P2P message payloads so that if there is a flag set in the message the payload should be decompressed and it's being done with
DecompressLz4that looks like this:So it's allocating a space 255 times more than the incoming compressed payload (of course limited by
PayloadMaxSize, but it's 32M which is quite a lot). It's obviously designed for the worst case lacking any real reference for the size, but these allocations seem to be wasteful as typical compression ratio is expected to be far lower than 255.Proposed changes
There are two basic approaches to solving it:
is the way it was originally implemented, see
TCP P2P optimization #710 (comment)), this
will make decompression just work.
contain an uint32 with the size of uncompressed payload, this would require
using the data from this field when decompressing, but it's trivial to do
I have a slight preference for the first one, but at the same time it's perfectly fine to do the second.
Expected effect
Reducing memory pressure in typical usage scenarios. This doesn't prevent malicious node from specifying
PayloadMaxSizefor decompressed size in all of its messages, but it at the same time makes the node use less memory for regular communication which I think is beneficial.Neo Version
Where in the software does this update applies to?