-
Notifications
You must be signed in to change notification settings - Fork 450
perf!: reduce linq, cleanup connectedclients #1196
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
2fa0f6d
c36b3af
5ac5ef9
4776737
f245150
fc944c4
cb95862
a3e0abc
ea31f10
057c1fc
63309e2
e9b9305
aa56440
fabb3b8
3a2a50b
58db1bd
c827339
f8bfb2f
9816b50
a576552
5193e39
119ee2f
7fb2d53
8ee4610
808f28a
81c3dc3
8dfa959
b24d1a7
441d933
1436cf8
90f41be
2957095
7a21615
1e8761b
89e66e8
7f95934
c788567
eb26475
d2a2635
3d176ee
b190a20
fa848a4
00c6f71
73a1e1f
e4db745
73b2071
3b71334
f23af57
d5f6436
0d065be
23b3039
e8b59c9
bdfc6e6
57b56c0
18a1d39
ad5d90a
b82e130
fcafdb3
cd7229a
1276dd6
34e0e6d
4ce41eb
20c91bc
e5ec6aa
4ec10a2
50cc9eb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,8 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is still here because of profiler stuff (which is really broken and needs a separate pass). It's now at the right position at least 🙃 |
||
using UnityEngine; | ||
using System.Reflection; | ||
using System.Linq; | ||
using Unity.Collections; | ||
|
||
namespace Unity.Netcode | ||
|
@@ -131,14 +131,7 @@ internal unsafe void __sendClientRpc(FastBufferWriter writer, uint rpcMethodId, | |
|
||
if (rpcParams.Send.TargetClientIds != null) | ||
{ | ||
// Copy into a localArray because SendMessage doesn't take IEnumerable, only IReadOnlyList | ||
ulong* localArray = stackalloc ulong[rpcParams.Send.TargetClientIds.Count()]; | ||
var index = 0; | ||
foreach (var clientId in rpcParams.Send.TargetClientIds) | ||
{ | ||
localArray[index++] = clientId; | ||
} | ||
messageSize = NetworkManager.SendMessage(message, networkDelivery, localArray, index, true); | ||
messageSize = NetworkManager.SendMessage(message, networkDelivery, in rpcParams.Send.TargetClientIds, true); | ||
} | ||
else if (rpcParams.Send.TargetClientIdsNativeArray != null) | ||
{ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,6 @@ | ||
using System; | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using Unity.Collections; | ||
using Unity.Collections.LowLevel.Unsafe; | ||
using UnityEngine; | ||
|
@@ -251,20 +250,61 @@ internal set | |
|
||
private ulong m_LocalClientId; | ||
|
||
private Dictionary<ulong, NetworkClient> m_ConnectedClients = new Dictionary<ulong, NetworkClient>(); | ||
|
||
private List<NetworkClient> m_ConnectedClientsList = new List<NetworkClient>(); | ||
|
||
private List<ulong> m_ConnectedClientIds = new List<ulong>(); | ||
|
||
/// <summary> | ||
/// Gets a dictionary of connected clients and their clientId keys. This is only populated on the server. | ||
/// Gets a dictionary of connected clients and their clientId keys. This is only accessible on the server. | ||
/// </summary> | ||
public readonly Dictionary<ulong, NetworkClient> ConnectedClients = new Dictionary<ulong, NetworkClient>(); | ||
public IReadOnlyDictionary<ulong, NetworkClient> ConnectedClients | ||
{ | ||
get | ||
{ | ||
if (IsServer == false) | ||
{ | ||
throw new NotServerException($"{nameof(ConnectedClients)} should only be accessed on server."); | ||
} | ||
return m_ConnectedClients; | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Gets a list of connected clients. This is only populated on the server. | ||
/// Gets a list of connected clients. This is only accessible on the server. | ||
/// </summary> | ||
public readonly List<NetworkClient> ConnectedClientsList = new List<NetworkClient>(); | ||
public IReadOnlyList<NetworkClient> ConnectedClientsList | ||
{ | ||
get | ||
{ | ||
if (IsServer == false) | ||
{ | ||
throw new NotServerException($"{nameof(ConnectedClientsList)} should only be accessed on server."); | ||
} | ||
return m_ConnectedClientsList; | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Gets a list of just the IDs of all connected clients. | ||
/// Gets a list of just the IDs of all connected clients. This is only accessible on the server. | ||
/// </summary> | ||
public ulong[] ConnectedClientsIds => ConnectedClientsList.Select(c => c.ClientId).ToArray(); | ||
public IReadOnlyList<ulong> ConnectedClientsIds | ||
{ | ||
get | ||
{ | ||
if (IsServer == false) | ||
{ | ||
throw new NotServerException($"{nameof(m_ConnectedClientIds)} should only be accessed on server."); | ||
} | ||
return m_ConnectedClientIds; | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Gets the local <see cref="NetworkClient"/> for this client. | ||
/// </summary> | ||
public NetworkClient LocalClient { get; internal set; } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see this getting set in connection approval, but I don't ever see it unset? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes this was already an issue before where ConnectedClients was not cleared until the next initialize. I added a line which clears LocalClient in initialize. So this will behave differently as before which is not ideal behavior but I think we decided to touch the initialization/shutdown flow it should be in a separate PR. |
||
|
||
/// <summary> | ||
/// Gets a dictionary of the clients that have been accepted by the transport but are still pending by the Netcode. This is only populated on the server. | ||
|
@@ -468,8 +508,10 @@ private void Initialize(bool server) | |
LocalClientId = ulong.MaxValue; | ||
|
||
PendingClients.Clear(); | ||
ConnectedClients.Clear(); | ||
ConnectedClientsList.Clear(); | ||
m_ConnectedClients.Clear(); | ||
m_ConnectedClientsList.Clear(); | ||
m_ConnectedClientIds.Clear(); | ||
LocalClient = null; | ||
NetworkObject.OrphanChildren.Clear(); | ||
|
||
// Create spawn manager instance | ||
|
@@ -1415,12 +1457,21 @@ private void OnClientDisconnectFromServer(ulong clientId) | |
{ | ||
if (ConnectedClientsList[i].ClientId == clientId) | ||
{ | ||
ConnectedClientsList.RemoveAt(i); | ||
m_ConnectedClientsList.RemoveAt(i); | ||
break; | ||
} | ||
} | ||
|
||
for (int i = 0; i < ConnectedClientsIds.Count; i++) | ||
{ | ||
if (ConnectedClientsIds[i] == clientId) | ||
{ | ||
m_ConnectedClientIds.RemoveAt(i); | ||
break; | ||
} | ||
} | ||
|
||
ConnectedClients.Remove(clientId); | ||
m_ConnectedClients.Remove(clientId); | ||
} | ||
m_MessagingSystem.ClientDisconnected(clientId); | ||
} | ||
|
@@ -1462,8 +1513,9 @@ internal void HandleApproval(ulong ownerClientId, bool createPlayerObject, uint? | |
PendingClients.Remove(ownerClientId); | ||
|
||
var client = new NetworkClient { ClientId = ownerClientId, }; | ||
ConnectedClients.Add(ownerClientId, client); | ||
ConnectedClientsList.Add(client); | ||
m_ConnectedClients.Add(ownerClientId, client); | ||
m_ConnectedClientsList.Add(client); | ||
m_ConnectedClientIds.Add(client.ClientId); | ||
|
||
if (createPlayerObject) | ||
{ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,7 +25,7 @@ public struct ClientRpcSendParams | |
/// Note: Even if you provide a value type such as NativeArray, enumerating it will cause boxing. | ||
/// If you want to avoid boxing, use TargetClientIdsNativeArray | ||
/// </summary> | ||
public IEnumerable<ulong> TargetClientIds; | ||
public IReadOnlyList<ulong> TargetClientIds; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If this becomes IReadOnlyList, then NetworkBehaviour.SendClientRpc() can be adjusted to not have to make a copy of it and just pass it directly to SendMessage() :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes you are right, simplified the code to use the SendMessage overload with IReadOnlyList. |
||
|
||
/// <summary> | ||
/// NativeArray version of target id list - use either this OR TargetClientIds | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Cosmin-B what do you think should we do this or keep linq here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. Also, is worth noting that this call would not happen frequently at all... so the performance benefit is super tiny.