Search Unity

Ridiculous amount of overhead on commands? Is this right?

Discussion in 'Multiplayer' started by PrimeDerektive, Sep 11, 2017.

  1. PrimeDerektive

    PrimeDerektive

    Joined:
    Dec 13, 2009
    Posts:
    3,090
    I discovered NetworkTransport.GetOutgoingFullBytesCount thanks to the forums and set up a GUI to show my clients outgoing bytes per second, which is great. But I setup a simple script that just sends a command 10x a second to the host with 6 Vector3's, which should be 72 bytes, x10, so 720 bytes/sec.

    I expect some overhead, but NetworkTransport is reporting that its sending 1640 bytes per second, without fail. I'm using an unreliable channel too. That means there's, what, 92 bytes of overhead per command? How is that possible? That can't be right.... Right?
     
    Whippets and daxiongmao like this.
  2. marcV2g

    marcV2g

    Joined:
    Jan 11, 2016
    Posts:
    115
    Is it on the reliable channel?
     
  3. PrimeDerektive

    PrimeDerektive

    Joined:
    Dec 13, 2009
    Posts:
    3,090
    Nope, unreliable.
     
  4. Deleted User

    Deleted User

    Guest

    Edan-Smith likes this.
  5. PrimeDerektive

    PrimeDerektive

    Joined:
    Dec 13, 2009
    Posts:
    3,090
    Thanks, I’m aware of that though, I’m just sending the command in invokerepeating with 0.1f as the interval.
     
  6. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    Isn't the overhead going to include what channel, gameobject, and component for each command, plus whatever additional overhead is used when packaging the whole thing? 92 bytes in overhead per command does seem like a lot for that though.
     
  7. PrimeDerektive

    PrimeDerektive

    Joined:
    Dec 13, 2009
    Posts:
    3,090
    Here's my code, its super basic, in case anyone is wondering. Doing nothing but sending 6 Vector3's with a command, 10x per second:

    Code (csharp):
    1.  
    2.  
    3. using System.Collections;
    4. using System.Collections.Generic;
    5. using UnityEngine;
    6. using UnityEngine.Networking;
    7.  
    8. [NetworkSettings(channel = 1, sendInterval = 0.1f)]
    9. public class NetworkAvatarSync : NetworkBehaviour {
    10.  
    11.  
    12.     public float sendRate = 0.1f;
    13.     public Transform handLeft;
    14.     public Transform handRight;
    15.  
    16.     public override void OnStartLocalPlayer()
    17.     {
    18.         base.OnStartLocalPlayer();
    19.         InvokeRepeating("SendStateToServer", 0, sendRate);
    20.     }
    21.  
    22.     void SendStateToServer()
    23.     {
    24.         CmdReceiveState(transform.position, transform.eulerAngles, handLeft.position, handLeft.eulerAngles, handRight.position, handRight.eulerAngles);
    25.     }
    26.  
    27.     [Command]
    28.     void CmdReceiveState(Vector3 headPos, Vector3 headEulers, Vector3 handLeftPos, Vector3 handLeftEulers, Vector3 handRightPos, Vector3 handRightEulers)
    29.     {
    30.         Debug.Log("Received VR Avatar pos/rot state.");
    31.     }
    32.  
    33. }
    34.  
    35.  
    and the traffic monitor:

    Code (csharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using UnityEngine.Networking;
    6. using UnityEngine.UI;
    7.  
    8. public class NetworkAvatarStatsUI : NetworkBehaviour {
    9.  
    10.     int newBytes = 0;
    11.     int lastBytes = 0;
    12.  
    13.     public override void OnStartLocalPlayer()
    14.     {
    15.         base.OnStartLocalPlayer();
    16.         InvokeRepeating("RecordAndDisplayBytes", 0.0f, 1.0f);
    17.     }
    18.  
    19.     void RecordAndDisplayBytes()
    20.     {
    21.         lastBytes = newBytes;
    22.         newBytes = NetworkTransport.GetOutgoingFullBytesCount();
    23.         if(lastBytes != 0 && newBytes != 0)
    24.         {
    25.             int bytesLastSecond = newBytes - lastBytes;
    26.             Debug.Log("Outgoing bytes per second: " + bytesLastSecond.ToString());
    27.         }
    28.     }
    29.  
    30. }
    31.  
    32.  
     
    Last edited: Sep 12, 2017
    Deleted User likes this.
  8. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    My guess is its all the other stuff going on behind the scenes.
    For example, even though you arent sending any reliable packets, assuming you have added reliable channel of some sort (which the hlapi does by default as channel 0) then each packet might always have at least 4 bytes for the 32 acks. 4 * 10 = 40 bytes already.
    The cmd header seems to be this
    Code (CSharp):
    1.     public struct CommandMessage
    2.     {
    3.         public int cmdHash;
    4.         public string cmdName;
    5.         public byte[] payload;
    6.     }
    https://bitbucket.org/Unity-Technol...a9a3fc33cdad2f9bb1/Runtime/Messages.cs?at=5.3
    So lets say thats 4 bytes for the hash and your Cmd is 15 characters so lets just say 15 bytes.
    Then the packet headers themselves are like 10 bytes of stuff, then 1 byte for length of message if its <= 240, and 1 byte for channelID.
    Docs also says GetOutgoingFullBytesCount includes ip address and udp header...
    So yea, it probably all adds up =\
     
  9. moco2k

    moco2k

    Joined:
    Apr 29, 2015
    Posts:
    294
    I would like to suggest to also add RPCs to the test case. Also, it would be great if @aabramychev can chime in to provide an official answer on this.
     
  10. PrimeDerektive

    PrimeDerektive

    Joined:
    Dec 13, 2009
    Posts:
    3,090
    Yeah that would be great, I'd also like to know if NetworkTransport.GetOutgoingFullBytesCount() is the appropriate function to use to determine a user's outgoing send rate (i basically just want to know how close to the UNET relay 4kb limit I'm getting); I didn't know it included my IP and udp header like @HiddenMonk mentioned, not sure if that makes a difference/is necessary to account for when concerning my usage of the relay.
     
  11. Driiades

    Driiades

    Joined:
    Oct 27, 2015
    Posts:
    151
    Code (CSharp):
    1.     public struct CommandMessage
    2.     {
    3.         public int cmdHash;
    4.         public string cmdName;
    5.         public byte[] payload;
    6.     }
    @aabramychev omg, can you change the cmdName ? Why need this ?

    Just send an int, bake the function associated to the int in each client with an algorithm (alphabetic order or what you want, we don't care, it have to be reflexive and injective (I'm french, it's called like that ==> https://en.wikipedia.org/wiki/Reflexive_relation ).

    You send the baked int, you find the gameObject by your cmdHash and you find the function by the baked int on client with a simple array (the int is the index) of functions.

    Maybe you have some others technicals problems, maybe you have already solved this. But sincerely, why a striiing ? ^^
     
    Last edited: Sep 13, 2017
  12. PrimeDerektive

    PrimeDerektive

    Joined:
    Dec 13, 2009
    Posts:
    3,090
    Agreed, sending a byte per character in your command name as a string is ludicrous. it STILL doesn’t explain why I’m getting 94 bytes of overhead per command though (940 bytes overhead per sec). With the 4K/sec limit that’s a fourth of my limit and I’m only syncing 10x per second.
     
  13. aabramychev

    aabramychev

    Unity Technologies

    Joined:
    Jul 17, 2012
    Posts:
    574
    72 command per sec means that each udp packet will contain only one message. Then let's calculate overhead
    2 bytes per connection number, + 4 bytes per packet and session +6 bytes if you have any reliable channel in config + 2 bytes per message + 1 byte delimiter. Total: 15 bytes. It what llapi will add to your message. You can check it with stat function as NetworkTransport.GetOutgoingFullBytesCount - will return full length, ...System..() will return llapi headers + payload and ...User..() will return payload only. What;s happened in HLAPI ypu can check by yourself, code is open. (The same thing is about changing names in HLAPI, code is open) If you have llapi questions you are welcome, I've never develop hlapi and here I'm just user like you :)
     
  14. PrimeDerektive

    PrimeDerektive

    Joined:
    Dec 13, 2009
    Posts:
    3,090
    I don think you read my post too well; tI’m not sending 72 commands per second, I’m sending 10 commands per second with a payload of 72 bytes. NetworkTransport is reporting each command is 164 bytes. That’s 92 bytes overhead, so your explanation of the overhead doesn’t add up.
     
  15. aabramychev

    aabramychev

    Unity Technologies

    Joined:
    Jul 17, 2012
    Posts:
    574
    I understand your post, just was unclear 10 commands per second means that each command will be sent in separate packet. Overhead of each packet I described above.
     
  16. PrimeDerektive

    PrimeDerektive

    Joined:
    Dec 13, 2009
    Posts:
    3,090
    Okay, I get it. So you're saying the LLAPI adds 15 bytes to my command, anything the HLAPI adds is ¯\_(ツ)_/¯ because you're the LLAPI guy.

    If you don't know where the other 77 bytes of overhead is coming from, is there a Unity employee that does? I understand I could dig into the HLAPI code myself, but if I wanted to write my own HLAPI, I would've went that route. I was kinda hoping the one Unity provided would be somewhat optimized.
     
  17. aabramychev

    aabramychev

    Unity Technologies

    Joined:
    Jul 17, 2012
    Posts:
    574
    Just realized that you did use NetworkTransport.GetOutgoingFullBytesCount, this function will calculate ip + udp headers too, so you will need to add 20 bytes for ip (or 40 if you have ipv6 enabled) + 8 bytes udp.

    So worst case llapi + ip headers: 15 + 40 + 8 == 63 bytes ...
     
  18. PrimeDerektive

    PrimeDerektive

    Joined:
    Dec 13, 2009
    Posts:
    3,090
    All that still counts against my relay bandwidth usage, yeah?
     
  19. aabramychev

    aabramychev

    Unity Technologies

    Joined:
    Jul 17, 2012
    Posts:
    574
    I guess it will 20 bytes less as you access to relay over ipv4 now. You can check you physical traffic by using netstat or perfmon... And yes it will counts against bandwidth usage.