mirror of
https://github.com/MirrorNetworking/Mirror.git
synced 2024-11-18 02:50:32 +00:00
perf: remove allocations during syncvar sync (#946)
This commit is contained in:
parent
3ee87fe7de
commit
d2381ce892
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user