Search Unity

com.unity.transport - comment mistake? PopEvent When Stalled Previous Frame

Discussion in 'Multiplayer' started by CPlusSharp22, Jul 14, 2020.

  1. CPlusSharp22

    CPlusSharp22

    Joined:
    Dec 1, 2012
    Posts:
    111
    I'm looking for some validation of my thoughts to make sure I'm not using the API wrong and doing something undefined. The API has a comment in the implementation that looks invalid/out of date.

    Say you have a situation where your frame has stalled for a good amount of time. The server is spamming you the UDP packets which you'd normally be processing 1 or 2 at a time at most if you were running with no major stall.

    The stall ends and the next frame arrives. Now you have 40+ DataType pending packets sitting in the NetworkDriver of com.unity.transport and from user code (aka the game), you do the traditional while(socket.PopEvent != EventType.Empty)

    You'll now potentially hold up the frame popping and handling those backed up pending packets. Unfortunately, I'm encountering this and with my design, but I don't need to care about 39 of those packets (assuming they're all Data event typed ;) ). I only care about the very most recent packet received. Even if they're out of order and the most recent packet was just late to the party, the cost of a few ms of latency is better than the cost of in processing everything!

    Unfortunately, it appears com.unity.transport may not have a way of doing this. But, I'm not entirely positive either due to an outdated comment in the implentation.
    There's no API to poke at the event queue, so you don't know how many times socket.PopEvent will return valid events. You also don't know when you'll encounter a Connect or Disconnect event, which makes sense - it's a queue.
    So the idea is: what if we just socket.PopEvent until there's no more DataEvent types, and then only process the last DataEvent popped? Sounds simple!

    Unfortunately, there's a mysterious and frightening comment in com.unity.transport that suggests to never do this!?
    In NetworkEventQueue::PopEvent is says: "
    // The returned stream is valid until PopEvent is called again or until the main driver updates
    "

    So every time you call PopEvent, it will invalidate the previous event.... or so it says!? The catch: I don't see any code in here that suggests that comment is true! Is it misleading?
    NetworkEventQueue::popEvents calls and returns simple offset indexes to a buffer from within PopEventForConnection. A DataStreamReader is made using these offsets and provided to user code. But nowhere in any of this is it disposing of the underlying data that the offsets point to! The only time a NetworkEvent is disposed of is in a ClearEventQueue() which is only called on driver update!

    So my idea of storing the last popped data network event until socket.PopEvent returns a disconnect or empty should work right? I mean, it seems to work but I've done things before that work only by chance that were undefined behavior o_O