Synced arrays have about 40 bytes of overhead which I cannot explain how those bytes could be used internally.
For a long time I thought synced objects had 12 bytes of base overhead, 4 bytes of overhead per synced variable and then the actual variable data. That would explain the 20 bytes for a single synced int... though the single synced byte with 14 is new to me.
Either way, in the case of a script with a single synced byte array, let's assume the 12 + 4 bytes of overhead are correct (base + per variable), so that's 16. Then let's assume it stores the length of the array in an int, even though that could be done in a space optimized way, but let's just go with 4. That's 20 bytes of total expected overhead for a script with a single synced byte array. However as we can see in the demo log output at the end, it's 64 byteCount when syncing an empty byte array.
Ok but where is the issue?
I've created a lockstep networking implementation on top of VRChat's networking. It requires "heartbeats" to be sent by a tick sync script, that's how clients know they're allowed to advance to the next tick(s). This script sends both the current tick as well as all associated input action ids. Must be in the same script to avoid race conditions. That's a variable amount of data, so it must use an array (I ended up just using a single byte array for all synced data). Even if no input actions are sent and it just syncs the current tick, that's 68 bytes per sync, which at a tickrate of 10 equates to 680 bytes per second, which is over 5% of the 11kb global manually synced limit. I wanted a tickrate of 20, but then we're at 10% while the system is effectively idle. Not to mention that to my knowledge avatar syncing also counts to this 11kb limit. Ultimately I feel bad for wasting both server and user bandwidth... but it is outside of my control. The actual payload is just 2 to 3 bytes per sync (because ticks (uint) are serialized in a space optimized way), so 97% to 95.5% is overhead. Reducing the overhead by 66% (getting rid of those 40 unknown bytes) would be huge.
I think there's a high chance for this to be unintended behavior, so the bug report category fits best.
Potential demo log output: (<dlt> stands for debug log tracker, so not actually relevant)
<dlt> single synced byte variable - result.success: True, result.byteCount: 14
<dlt> single synced int variable - result.success: True, result.byteCount: 20
<dlt> result.success: True, result.byteCount: 64, data.Length: 0
<dlt> result.success: True, result.byteCount: 68, data.Length: 1
<dlt> result.success: True, result.byteCount: 68, data.Length: 2
<dlt> result.success: True, result.byteCount: 68, data.Length: 3
<dlt> result.success: True, result.byteCount: 68, data.Length: 4
<dlt> result.success: True, result.byteCount: 72, data.Length: 5
<dlt> result.success: True, result.byteCount: 72, data.Length: 6
<dlt> result.success: True, result.byteCount: 72, data.Length: 7
<dlt> result.success: True, result.byteCount: 72, data.Length: 8
<dlt> result.success: True, result.byteCount: 76, data.Length: 9
<dlt> result.success: True, result.byteCount: 76, data.Length: 10