Skip to content

Commit 3dcc65a

Browse files
fix: Removed unnecessary GC Allocation (#3527)
Fix for [MTTB-85](https://jira.unity3d.com/browse/MTTB-85) removed the use of a foreach causing an unnecessary GC Allocation. Did a full sweep of internal `NetworkManager.ConnectedClientsIds` and replaced with either `for` loop or directly referencing the `NetworkConnectionManager.ConnectedClientIds`. ## Changelog - Fixed: Issue with unnecessary internal GC Allocations when using the `IReadOnlyList` `NetworkManager.ConnectedClientsIds` within a `foreach` statement by either replacing with a `for` loop or directly referencing the `NetworkConnectionManager.ConnectedClientIds`. ## Documentation - No documentation updates were required. ## Testing & QA [//]: # ( This section is REQUIRED and should describe how the changes were tested and how should they be tested when Playtesting for the release. It can range from "edge case covered by unit tests" to "manual testing required and new sample was added". Expectation is that PR creator does some manual testing and provides a summary of it here.) ### Functional Testing [//]: # (If checked, List manual tests that have been performed.) _Manual testing :_ - [X] `Manual testing done` - Tested manually before and after fix to confirm the allocation was present and then absent. _Automated tests:_ - [ ] `Covered by existing automated tests` - [ ] `Covered by new automated tests` _Does the change require QA team to:_ - [ ] `Review automated tests`? - [ ] `Execute manual tests`? If any boxes above are checked, please add QA as a PR reviewer. ## Backport The backport of this PR is #3601 --------- Co-authored-by: NoelStephensUnity <[email protected]>
1 parent 46fa369 commit 3dcc65a

18 files changed

+37
-29
lines changed

com.unity.netcode.gameobjects/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Additional documentation and release notes are available at [Multiplayer Documen
1717
- Fixed an issue where `UnityTransport` would not accept single words as valid hostnames (notably "localhost"). (#3591)
1818
- Fixed issue where viewing a `NetworkBehaviour` with one or more `NetworkVariable` fields could throw an exception if running a distributed authority network topology with a local (DAHost) host and viewed on the host when the host is not the authority of the associated `NetworkObject`. (#3578)
1919
- Fixed issue when using a distributed authority network topology and viewing a `NetworkBehaviour` with one or more `NetworkVariable` fields in the inspector view would not show editable fields. (#3578)
20+
- Fixed issue with unnecessary internal GC Allocations when using the `IReadOnlyList` `NetworkManager.ConnectedClientsIds` within a `foreach` statement by either replacing with a `for` loop or directly referencing the `NetworkConnectionManager.ConnectedClientIds`. (#3527)
2021

2122
### Changed
2223

com.unity.netcode.gameobjects/Runtime/Components/NetworkAnimator.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -996,7 +996,7 @@ internal void CheckForAnimatorChanges()
996996
{
997997
// Just notify all remote clients and not the local server
998998
m_ClientSendList.Clear();
999-
foreach (var clientId in NetworkManager.ConnectedClientsIds)
999+
foreach (var clientId in NetworkManager.ConnectionManager.ConnectedClientIds)
10001000
{
10011001
if (clientId == NetworkManager.LocalClientId || !NetworkObject.Observers.Contains(clientId))
10021002
{
@@ -1315,7 +1315,7 @@ private unsafe void SendParametersUpdateServerRpc(ParametersUpdateMessage parame
13151315
if (NetworkManager.ConnectedClientsIds.Count > (IsHost ? 2 : 1))
13161316
{
13171317
m_ClientSendList.Clear();
1318-
foreach (var clientId in NetworkManager.ConnectedClientsIds)
1318+
foreach (var clientId in NetworkManager.ConnectionManager.ConnectedClientIds)
13191319
{
13201320
if (clientId == serverRpcParams.Receive.SenderClientId || clientId == NetworkManager.ServerClientId || !NetworkObject.Observers.Contains(clientId))
13211321
{
@@ -1378,7 +1378,7 @@ private void SendAnimStateServerRpc(AnimationMessage animationMessage, ServerRpc
13781378
if (NetworkManager.ConnectedClientsIds.Count > (IsHost ? 2 : 1))
13791379
{
13801380
m_ClientSendList.Clear();
1381-
foreach (var clientId in NetworkManager.ConnectedClientsIds)
1381+
foreach (var clientId in NetworkManager.ConnectionManager.ConnectedClientIds)
13821382
{
13831383
if (clientId == serverRpcParams.Receive.SenderClientId || clientId == NetworkManager.ServerClientId || !NetworkObject.Observers.Contains(clientId))
13841384
{
@@ -1452,7 +1452,7 @@ internal void SendAnimTriggerServerRpc(AnimationTriggerMessage animationTriggerM
14521452
InternalSetTrigger(animationTriggerMessage.Hash, animationTriggerMessage.IsTriggerSet);
14531453

14541454
m_ClientSendList.Clear();
1455-
foreach (var clientId in NetworkManager.ConnectedClientsIds)
1455+
foreach (var clientId in NetworkManager.ConnectionManager.ConnectedClientIds)
14561456
{
14571457
if (clientId == NetworkManager.ServerClientId || !NetworkObject.Observers.Contains(clientId))
14581458
{

com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,12 +149,12 @@ internal void InvokeOnClientConnectedCallback(ulong clientId)
149149
}
150150

151151
// Invoking connection event on non-authority local client. Need to calculate PeerIds.
152-
var peerClientIds = new NativeArray<ulong>(Math.Max(NetworkManager.ConnectedClientsIds.Count - 1, 0), Allocator.Temp);
152+
var peerClientIds = new NativeArray<ulong>(Math.Max(ConnectedClientIds.Count - 1, 0), Allocator.Temp);
153153
// `using var peerClientIds` or `using(peerClientIds)` renders it immutable...
154154
using var sentinel = peerClientIds;
155155

156156
var idx = 0;
157-
foreach (var peerId in NetworkManager.ConnectedClientsIds)
157+
foreach (var peerId in ConnectedClientIds)
158158
{
159159
if (peerId == NetworkManager.LocalClientId)
160160
{

com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1616,7 +1616,7 @@ public void NetworkHide(ulong clientId)
16161616
// Send destroy call
16171617
size = NetworkManager.ConnectionManager.SendMessage(ref message, NetworkDelivery.ReliableSequenced, clientId);
16181618
// Broadcast the destroy to all clients so they can update their observers list
1619-
foreach (var client in NetworkManager.ConnectedClientsIds)
1619+
foreach (var client in NetworkManager.ConnectionManager.ConnectedClientIds)
16201620
{
16211621
if (client == clientId || client == NetworkManager.LocalClientId)
16221622
{
@@ -2363,7 +2363,7 @@ private void OnTransformParentChanged()
23632363
}
23642364
else
23652365
{
2366-
foreach (var clientId in NetworkManager.ConnectedClientsIds)
2366+
foreach (var clientId in NetworkManager.ConnectionManager.ConnectedClientIds)
23672367
{
23682368
if (clientId == NetworkManager.ServerClientId)
23692369
{
@@ -2382,7 +2382,7 @@ private void OnTransformParentChanged()
23822382
var maxCount = NetworkManager.ConnectedClientsIds.Count;
23832383
ulong* clientIds = stackalloc ulong[maxCount];
23842384
int idx = 0;
2385-
foreach (var clientId in NetworkManager.ConnectedClientsIds)
2385+
foreach (var clientId in NetworkManager.ConnectionManager.ConnectedClientIds)
23862386
{
23872387
if (clientId == NetworkManager.ServerClientId)
23882388
{

com.unity.netcode.gameobjects/Runtime/Messaging/Messages/ChangeOwnershipMessage.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,9 @@ public void Handle(ref NetworkContext context)
250250
}
251251
else
252252
{
253-
foreach (var clientId in clientList)
253+
for (int i = 0; i < clientList.Count; i++)
254254
{
255+
var clientId = clientList[i];
255256
if (clientId == networkManager.LocalClientId)
256257
{
257258
continue;

com.unity.netcode.gameobjects/Runtime/Messaging/Messages/CreateObjectMessage.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,9 +247,9 @@ internal static void CreateObject(ref NetworkManager networkManager, ulong sende
247247
var clientList = hasObserverIdList && !networkObject.IsPlayerObject ? observerIds : networkManager.ConnectedClientsIds;
248248

249249
// Update the observers for this instance
250-
foreach (var clientId in clientList)
250+
for (int i = 0; i < clientList.Count; i++)
251251
{
252-
networkObject.Observers.Add(clientId);
252+
networkObject.Observers.Add(clientList[i]);
253253
}
254254

255255
// Mock CMB Service and forward to all clients

com.unity.netcode.gameobjects/Runtime/Messaging/Messages/DestroyObjectMessage.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ private void HandleDAHostForwardMessage(ulong senderId, ref NetworkManager netwo
191191
DeferredDespawnTick = DeferredDespawnTick,
192192
};
193193
var ownerClientId = networkObject == null ? senderId : networkObject.OwnerClientId;
194-
var clientIds = networkObject == null ? networkManager.ConnectedClientsIds.ToList() : networkObject.Observers.ToList();
194+
var clientIds = networkObject == null ? networkManager.ConnectionManager.ConnectedClientIds : networkObject.Observers.ToList();
195195

196196
foreach (var clientId in clientIds)
197197
{

com.unity.netcode.gameobjects/Runtime/Messaging/Messages/NetworkVariableDeltaMessage.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ public void Handle(ref NetworkContext context)
228228
if (isServerAndDeltaForwarding)
229229
{
230230
m_ForwardUpdates = new Dictionary<ulong, List<int>>();
231-
foreach (var clientId in networkManager.ConnectedClientsIds)
231+
foreach (var clientId in networkManager.ConnectionManager.ConnectedClientIds)
232232
{
233233
if (clientId == context.SenderId || clientId == networkManager.LocalClientId || !networkObject.Observers.Contains(clientId))
234234
{

com.unity.netcode.gameobjects/Runtime/Messaging/RpcTargets/BaseRpcTarget.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ public abstract class BaseRpcTarget : IDisposable
1111
/// The <see cref="NetworkManager"/> instance which can be used to handle sending and receiving the specific target(s)
1212
/// </summary>
1313
protected NetworkManager m_NetworkManager;
14+
15+
internal NetworkConnectionManager ConnectionManager;
1416
private bool m_Locked;
1517

1618
internal void Lock()
@@ -26,6 +28,7 @@ internal void Unlock()
2628
internal BaseRpcTarget(NetworkManager manager)
2729
{
2830
m_NetworkManager = manager;
31+
ConnectionManager = m_NetworkManager.ConnectionManager;
2932
}
3033

3134
/// <summary>

com.unity.netcode.gameobjects/Runtime/Messaging/RpcTargets/NotAuthorityRpcTarget.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ internal override void Send(NetworkBehaviour behaviour, ref RpcMessage message,
4040
}
4141
else
4242
{
43-
foreach (var clientId in m_NetworkManager.ConnectedClientsIds)
43+
foreach (var clientId in ConnectionManager.ConnectedClientIds)
4444
{
4545
if (clientId == behaviour.OwnerClientId || !networkObject.Observers.Contains(clientId))
4646
{

0 commit comments

Comments
 (0)