Skip to content

Use stream lz4 for P2P messages or specify decoded payload size #1746

@roman-khimov

Description

@roman-khimov

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 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?

  • P2P (TCP)

Metadata

Metadata

Assignees

No one assigned

    Labels

    DiscussionInitial issue state - proposed but not yet accepted

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions