perf: remove allocations during syncvar sync (#946)

This commit is contained in:
Paul Pacheco 2019-07-01 16:12:02 -05:00 committed by vis2k
parent 3ee87fe7de
commit d2381ce892
2 changed files with 24 additions and 21 deletions

View File

@ -573,28 +573,21 @@ bool OnSerializeSafely(NetworkBehaviour comp, NetworkWriter writer, bool initial
return result;
}
// OnSerializeAllSafely is in hot path. caching the writer is really
// worth it to avoid large amounts of allocations.
static NetworkWriter onSerializeWriter = new NetworkWriter();
// serialize all components (or only dirty ones if not initial state)
// -> returns serialized data of everything dirty, null if nothing was dirty
internal byte[] OnSerializeAllSafely(bool initialState)
// -> returns true if something was written
internal bool OnSerializeAllSafely(bool initialState, NetworkWriter writer)
{
// reset cached writer length and position
onSerializeWriter.SetLength(0);
if (networkBehavioursCache.Length > 64)
{
Debug.LogError("Only 64 NetworkBehaviour components are allowed for NetworkIdentity: " + name + " because of the dirtyComponentMask");
return null;
return false;
}
ulong dirtyComponentsMask = GetDirtyMask(networkBehavioursCache, initialState);
if (dirtyComponentsMask == 0L)
return null;
return false;
onSerializeWriter.WritePackedUInt64(dirtyComponentsMask); // WritePacked64 so we don't write full 8 bytes if we don't have to
writer.WritePackedUInt64(dirtyComponentsMask); // WritePacked64 so we don't write full 8 bytes if we don't have to
foreach (NetworkBehaviour comp in networkBehavioursCache)
{
@ -605,7 +598,7 @@ internal byte[] OnSerializeAllSafely(bool initialState)
{
// serialize the data
if (LogFilter.Debug) Debug.Log("OnSerializeAllSafely: " + name + " -> " + comp.GetType() + " initial=" + initialState);
OnSerializeSafely(comp, onSerializeWriter, initialState);
OnSerializeSafely(comp, writer, initialState);
// Clear dirty bits only if we are synchronizing data and not sending a spawn message.
// This preserves the behavior in HLAPI
@ -616,7 +609,7 @@ internal byte[] OnSerializeAllSafely(bool initialState)
}
}
return onSerializeWriter.ToArray();
return true;
}
ulong GetDirtyMask(NetworkBehaviour[] components, bool initialState)
@ -1037,17 +1030,18 @@ internal void MirrorUpdate()
if (observers == null || observers.Count == 0)
return;
NetworkWriter writer = NetworkWriterPool.GetWriter();
// serialize all the dirty components and send (if any were dirty)
byte[] payload = OnSerializeAllSafely(false);
if (payload != null)
if (OnSerializeAllSafely(false, writer))
{
// populate cached UpdateVarsMessage and send
varsMessage.netId = netId;
// segment to avoid reader allocations.
// (never null because of our above check)
varsMessage.payload = new ArraySegment<byte>(payload);
varsMessage.payload = writer.ToArraySegment();
NetworkServer.SendToReady(this, varsMessage);
}
NetworkWriterPool.Recycle(writer);
}
}
}

View File

@ -836,13 +836,20 @@ internal static void SendSpawnMessage(NetworkIdentity identity, NetworkConnectio
if (LogFilter.Debug) Debug.Log("Server SendSpawnMessage: name=" + identity.name + " sceneId=" + identity.sceneId.ToString("X") + " netid=" + identity.netId); // for easier debugging
// serialize all components with initialState = true
// (can be null if has none)
byte[] serialized = identity.OnSerializeAllSafely(true);
NetworkWriter writer = NetworkWriterPool.GetWriter();
// convert to ArraySegment to avoid reader allocations
// (need to handle null case too)
ArraySegment<byte> segment = serialized != null ? new ArraySegment<byte>(serialized) : default;
ArraySegment<byte> segment = default;
// serialize all components with initialState = true
// (can be null if has none)
if (identity.OnSerializeAllSafely(true, writer))
{
segment = writer.ToArraySegment();
}
// 'identity' is a prefab that should be spawned
if (identity.sceneId == 0)
@ -896,6 +903,8 @@ internal static void SendSpawnMessage(NetworkIdentity identity, NetworkConnectio
SendToReady(identity, msg);
}
}
NetworkWriterPool.Recycle(writer);
}
public static void DestroyPlayerForConnection(NetworkConnection conn)