Skip to content

O(N^2) time complexity bug in WebsocketTransport #429

@dbregman

Description

@dbregman

_rxbuf.insert(_rxbuf.end(), _readbuf.begin(), _readbuf.begin() + ret);

_rxbuf.erase(_rxbuf.begin(), _rxbuf.begin() + ws.header_size + (size_t) ws.N);

The way the code is using std::vector for the receive buffer with data being added at the end and removed from the front creates a time complexity bug. When erasing at the front, vector::erase is O(N) where N is the size of the whole vec, not the size of the packet data being erased. That means that dequeuing all packets is actually O(N^2)

If for whatever reason the receive buffer grows big enough, the time to dequeue one packet can exceed the time to receive one packet at which point it's a downward spiral that cannot be recovered (the process will grind to a halt).

This is not just theoretical, I experienced it in production.

The issue can be fixed by using a different datastructure for the receive buffer, such as std::deque.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions