diff --git a/Assets/Mirage/Runtime/MessageHandler.cs b/Assets/Mirage/Runtime/MessageHandler.cs index 1677f490fe..8e764ad506 100644 --- a/Assets/Mirage/Runtime/MessageHandler.cs +++ b/Assets/Mirage/Runtime/MessageHandler.cs @@ -2,12 +2,14 @@ using System.Collections.Generic; using Mirage.Logging; using Mirage.Serialization; +using Unity.Profiling; using UnityEngine; namespace Mirage { public class MessageHandler : IMessageReceiver { + private static readonly ProfilerMarker handleMessageMarker = new ProfilerMarker(nameof(HandleMessage)); private static readonly ILogger logger = LogFactory.GetLogger(); private readonly bool _disconnectOnException; @@ -47,7 +49,10 @@ void AdapterFunction(INetworkPlayer player, NetworkReader reader) if (logger.LogEnabled()) logger.Log($"Receiving {typeof(T)} from {player}"); - handler.Invoke(player, message); + using (var _ = MessageIdCache.ReceiveMarker.Auto()) + { + handler.Invoke(player, message); + } } return AdapterFunction; } @@ -73,6 +78,8 @@ public void ClearHandlers() public void HandleMessage(INetworkPlayer player, ArraySegment packet) { + using var _ = handleMessageMarker.Auto(); + using (var networkReader = NetworkReaderPool.GetReader(packet, _objectLocator)) { diff --git a/Assets/Mirage/Runtime/NetworkIdentity.cs b/Assets/Mirage/Runtime/NetworkIdentity.cs index 8f124fed97..6c18551cc1 100644 --- a/Assets/Mirage/Runtime/NetworkIdentity.cs +++ b/Assets/Mirage/Runtime/NetworkIdentity.cs @@ -4,6 +4,7 @@ using Mirage.Logging; using Mirage.RemoteCalls; using Mirage.Serialization; +using Unity.Profiling; using UnityEngine; using UnityEngine.Serialization; @@ -103,6 +104,12 @@ namespace Mirage [HelpURL("https://miragenet.github.io/Mirage/docs/components/network-identity")] public sealed class NetworkIdentity : MonoBehaviour { + private static readonly ProfilerMarker rebuildObserversMarker = new ProfilerMarker(nameof(RebuildObservers)); + private static readonly ProfilerMarker onSerializeAllInitialMarker = new ProfilerMarker("OnSerializeAll_Initial"); + private static readonly ProfilerMarker onSerializeAllPartialMarker = new ProfilerMarker("OnSerializeAll_Partial"); + private static readonly ProfilerMarker onDeserializeAllInitialMarker = new ProfilerMarker("OnDeserializeAll_Initial"); + private static readonly ProfilerMarker onDeserializeAllPartialMarker = new ProfilerMarker("OnSerializeAll_Partial"); + private static readonly ILogger logger = LogFactory.GetLogger(); public NetworkSpawnSettings SpawnSettings = NetworkSpawnSettings.Default; @@ -675,6 +682,8 @@ private void OnSerialize(int i, NetworkBehaviour comp, NetworkWriter writer, boo /// internal (int ownerWritten, int observersWritten) OnSerializeAll(bool initialState, NetworkWriter ownerWriter, NetworkWriter observersWriter) { + using var _ = (initialState ? onSerializeAllInitialMarker : onSerializeAllPartialMarker).Auto(); + // how many times it written to (NOT BYTES) var ownerWritten = 0; var observersWritten = 0; @@ -765,6 +774,8 @@ internal bool StillDirty() internal void OnDeserializeAll(NetworkReader reader, bool initialState) { + using var _ = (initialState ? onDeserializeAllInitialMarker : onDeserializeAllPartialMarker).Auto(); + // set InitialState before deserializing so that syncvar hooks and other methods can check it InitialState = initialState; @@ -979,6 +990,7 @@ internal void GetNewObservers(HashSet observersSet, bool initial /// True if this is the first time. public void RebuildObservers(bool initialize) { + using var _ = rebuildObserversMarker.Auto(); // call OnRebuildObservers function GetNewObservers(newObservers, initialize); diff --git a/Assets/Mirage/Runtime/NetworkPlayer.cs b/Assets/Mirage/Runtime/NetworkPlayer.cs index b8053d0a41..679d7c5e1a 100644 --- a/Assets/Mirage/Runtime/NetworkPlayer.cs +++ b/Assets/Mirage/Runtime/NetworkPlayer.cs @@ -4,6 +4,7 @@ using Mirage.Logging; using Mirage.Serialization; using Mirage.SocketLayer; +using Unity.Profiling; using UnityEngine; namespace Mirage @@ -20,6 +21,9 @@ namespace Mirage /// public sealed class NetworkPlayer : INetworkPlayer { + private static readonly ProfilerMarker sendMessageMarker = new ProfilerMarker("SendMessage"); + private static readonly ProfilerMarker sendBytesMarker = new ProfilerMarker("SendBytes"); + private static readonly ProfilerMarker sendNotifyMarket = new ProfilerMarker("SendNotify"); private static readonly ILogger logger = LogFactory.GetLogger(typeof(NetworkPlayer)); private readonly HashSet _visList = new HashSet(); @@ -173,6 +177,9 @@ public NetworkPlayer(IConnection connection, bool isHost) /// public void Send(T message, Channel channelId = Channel.Reliable) { + using var _ = sendMessageMarker.Auto(); + using var __ = MessageIdCache.SendMarker.Auto(); + if (_isDisconnected) { return; } using (var writer = NetworkWriterPool.GetWriter()) @@ -194,6 +201,8 @@ public void Send(T message, Channel channelId = Channel.Reliable) /// public void Send(ArraySegment segment, Channel channelId = Channel.Reliable) { + using var _ = sendBytesMarker.Auto(); + if (_isDisconnected) { return; } if (channelId == Channel.Reliable) @@ -215,6 +224,8 @@ public void Send(ArraySegment segment, Channel channelId = Channel.Reliabl /// public void Send(T message, INotifyCallBack callBacks) { + using var _ = sendNotifyMarket.Auto(); + if (_isDisconnected) { return; } using (var writer = NetworkWriterPool.GetWriter()) diff --git a/Assets/Mirage/Runtime/NetworkServer.cs b/Assets/Mirage/Runtime/NetworkServer.cs index 39cb4d6e61..35f228fb1e 100644 --- a/Assets/Mirage/Runtime/NetworkServer.cs +++ b/Assets/Mirage/Runtime/NetworkServer.cs @@ -7,6 +7,7 @@ using Mirage.Logging; using Mirage.Serialization; using Mirage.SocketLayer; +using Unity.Profiling; using UnityEngine; using UnityEngine.Serialization; @@ -23,6 +24,7 @@ namespace Mirage [DisallowMultipleComponent] public class NetworkServer : MonoBehaviour { + private static readonly ProfilerMarker sendToManyMarker = new ProfilerMarker(nameof(SendToMany)); private static readonly ILogger logger = LogFactory.GetLogger(typeof(NetworkServer)); public bool EnablePeerMetrics; @@ -478,7 +480,7 @@ internal void AddLocalConnection(NetworkClient client, IConnection connection) [Obsolete("Use SendToAll(msg, authenticatedOnly, excludeLocalPlayer, channelId) instead")] public void SendToAll(T msg, bool excludeLocalPlayer, Channel channelId = Channel.Reliable) => SendToAll(msg, authenticatedOnly: false, excludeLocalPlayer, channelId); - + public void SendToAll(T msg, bool authenticatedOnly, bool excludeLocalPlayer, Channel channelId = Channel.Reliable) { if (authenticatedOnly) @@ -562,10 +564,13 @@ public static void SendToMany(List players, T msg, Channel ch /// /// Sends to list of players. - /// All other SendTo... functions call this, it dooes not do any extra checks, just serializes message if not empty, then sends it + /// All other SendTo... functions call this, it does not do any extra checks, just serializes message if not empty, then sends it /// public static void SendToMany(IReadOnlyList players, T msg, Channel channelId = Channel.Reliable) { + using var _ = sendToManyMarker.Auto(); + using var __ = MessageIdCache.SendMarker.Auto(); + // avoid serializing when list is empty if (players.Count == 0) return; diff --git a/Assets/Mirage/Runtime/Serialization/MessagePacker.cs b/Assets/Mirage/Runtime/Serialization/MessagePacker.cs index 2f6af6a863..0324f4fbe2 100644 --- a/Assets/Mirage/Runtime/Serialization/MessagePacker.cs +++ b/Assets/Mirage/Runtime/Serialization/MessagePacker.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using Unity.Profiling; namespace Mirage.Serialization { @@ -11,6 +12,9 @@ namespace Mirage.Serialization public static class MessageIdCache { public static readonly int Id = MessagePacker.GetId(typeof(T)); + + public static readonly ProfilerMarker SendMarker = new ProfilerMarker($"Send_{typeof(T).Name}"); + public static readonly ProfilerMarker ReceiveMarker = new ProfilerMarker($"Handle_{typeof(T).Name}"); } // message packing all in one place, instead of constructing headers in all @@ -26,6 +30,7 @@ public static class MessageIdCache // (probably even shorter) public static class MessagePacker { + private static readonly ProfilerMarker packMarker = new ProfilerMarker(nameof(Pack)); /// /// Backing field for /// @@ -82,11 +87,13 @@ public static int GetId(Type type) // and do an allocation free send before recycling it. public static void Pack(T message, NetworkWriter writer) { + using var _ = packMarker.Auto(); + // if it is a value type, just use typeof(T) to avoid boxing // this works because value types cannot be derived // if it is a reference type (for example IMessageBase), // ask the message for the real type - var id = default(T) == null && message != null + var id = default(T) == null && message != null // for class we need to use GetType incase T is base class ? GetId(message.GetType()) // for struct, we can use the cached Id diff --git a/Assets/Mirage/Runtime/ServerObjectManager.cs b/Assets/Mirage/Runtime/ServerObjectManager.cs index 7eb156cb43..5c03140c07 100644 --- a/Assets/Mirage/Runtime/ServerObjectManager.cs +++ b/Assets/Mirage/Runtime/ServerObjectManager.cs @@ -4,6 +4,7 @@ using Mirage.Logging; using Mirage.RemoteCalls; using Mirage.Serialization; +using Unity.Profiling; using UnityEngine; using Object = UnityEngine.Object; @@ -22,7 +23,15 @@ namespace Mirage [DisallowMultipleComponent] public class ServerObjectManager : MonoBehaviour { + private static readonly ProfilerMarker spawnMarker = new ProfilerMarker(nameof(SpawnSceneObjects)); + private static readonly ProfilerMarker addCharacterMarker = new ProfilerMarker(nameof(AddCharacter)); + private static readonly ProfilerMarker destroyObjectMarker = new ProfilerMarker(nameof(DestroyObject)); + private static readonly ProfilerMarker spawnVisibleObjectsMarker = new ProfilerMarker(nameof(SpawnVisibleObjects)); + private static readonly ProfilerMarker spawnSceneObjectsMarker = new ProfilerMarker(nameof(SpawnSceneObjects)); + private static readonly ProfilerMarker sendSpawnMessageMarker = new ProfilerMarker(nameof(SendSpawnMessage)); + private static readonly ILogger logger = LogFactory.GetLogger(typeof(ServerObjectManager)); + /// HashSet for NetworkIdentity that can be re-used without allocation private static HashSet _skipCache = new HashSet(); /// HashSet for NetworkIdentity that can be re-used without allocation @@ -196,6 +205,8 @@ public void AddCharacter(INetworkPlayer player, NetworkIdentity character, int p /// throw when the player already has a character public void AddCharacter(INetworkPlayer player, NetworkIdentity identity) { + using var _ = addCharacterMarker.Auto(); + // cannot have an existing player object while trying to Add another. if (player.HasCharacter) { @@ -347,6 +358,8 @@ public void Spawn(NetworkIdentity identity, INetworkPlayer owner) /// public void Spawn(NetworkIdentity identity) { + using var _ = spawnMarker.Auto(); + if (!_server || !_server.Active) { throw new InvalidOperationException("NetworkServer is not active. Cannot spawn objects without an active server."); @@ -379,6 +392,8 @@ public void Spawn(NetworkIdentity identity) internal void SendSpawnMessage(NetworkIdentity identity, INetworkPlayer player) { + using var _ = sendSpawnMessageMarker.Auto(); + logger.Assert(player.IsAuthenticated || !(identity.Visibility is AlwaysVisible), // can't use `is not` in unity2020 "SendSpawnMessage should only be called if player is authenticated, or there is custom visibility"); if (logger.LogEnabled()) logger.Log($"Server SendSpawnMessage: name={identity.name} sceneId={identity.SceneId:X} netId={identity.NetId}"); @@ -514,6 +529,8 @@ public void Destroy(NetworkIdentity identity, bool destroyServerObject = true) private void DestroyObject(NetworkIdentity identity, bool destroyServerObject) { + using var _ = destroyObjectMarker.Auto(); + if (logger.LogEnabled()) logger.Log("DestroyObject instance:" + identity.NetId); _server.World.RemoveIdentity(identity); @@ -568,6 +585,8 @@ internal bool ValidateSceneObject(NetworkIdentity identity) /// Thrown when server is not active public void SpawnSceneObjects() { + using var _ = spawnSceneObjectsMarker.Auto(); + // only if server active if (!_server || !_server.Active) throw new InvalidOperationException("Server was not active"); @@ -640,6 +659,8 @@ public void SpawnVisibleObjects(INetworkPlayer player, bool ignoreHasCharacter, /// NetworkIdentity to skip when spawning. Can be null public void SpawnVisibleObjects(INetworkPlayer player, bool ignoreHasCharacter, HashSet skip) { + using var _ = spawnVisibleObjectsMarker.Auto(); + // todo Call player.RemoveAllVisibleObjects() first so that it will send spawn message for objects destroyed in scene change if (!ignoreHasCharacter && !player.HasCharacter) diff --git a/Assets/Mirage/Runtime/SyncVarReceiver.cs b/Assets/Mirage/Runtime/SyncVarReceiver.cs index a16af869f9..b22108c0d1 100644 --- a/Assets/Mirage/Runtime/SyncVarReceiver.cs +++ b/Assets/Mirage/Runtime/SyncVarReceiver.cs @@ -1,5 +1,6 @@ using Mirage.Logging; using Mirage.Serialization; +using Unity.Profiling; using UnityEngine; namespace Mirage @@ -9,6 +10,7 @@ namespace Mirage /// public class SyncVarReceiver { + private static readonly ProfilerMarker onUpdateVarsMessageMarker = new ProfilerMarker(nameof(OnUpdateVarsMessage)); private static readonly ILogger logger = LogFactory.GetLogger(typeof(SyncVarReceiver)); private readonly IObjectLocator _objectLocator; @@ -46,6 +48,7 @@ public SyncVarReceiver(NetworkServer server, IObjectLocator objectLocator) private void OnUpdateVarsMessage(INetworkPlayer sender, UpdateVarsMessage msg) { + using var _ = onUpdateVarsMessageMarker.Auto(); if (logger.LogEnabled()) logger.Log("SyncVarReceiver.OnUpdateVarsMessage " + msg.NetId); if (_objectLocator.TryGetIdentity(msg.NetId, out var localObject)) diff --git a/Assets/Mirage/Runtime/SyncVarSender.cs b/Assets/Mirage/Runtime/SyncVarSender.cs index 1e381bc8d7..d2e4f60d0f 100644 --- a/Assets/Mirage/Runtime/SyncVarSender.cs +++ b/Assets/Mirage/Runtime/SyncVarSender.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using Mirage.Logging; using Mirage.Serialization; +using Unity.Profiling; using UnityEngine; namespace Mirage @@ -11,11 +12,14 @@ namespace Mirage /// public class SyncVarSender { + private static readonly ProfilerMarker syncVarSenderMarker = new ProfilerMarker(nameof(SyncVarSender)); + private static readonly ProfilerMarker sendUpdateVarsMessageMarker = new ProfilerMarker(nameof(SendUpdateVarsMessage)); private static readonly ILogger logger = LogFactory.GetLogger(); private readonly HashSet _dirtyObjects = new HashSet(); private readonly List _dirtyObjectsTmp = new List(); + public void AddDirtyObject(NetworkIdentity dirty) { var added = _dirtyObjects.Add(dirty); @@ -25,6 +29,8 @@ public void AddDirtyObject(NetworkIdentity dirty) internal void Update() { + using var _ = syncVarSenderMarker.Auto(); + if (_dirtyObjects.Count == 0) return; @@ -70,6 +76,7 @@ internal void Update() internal static void SendUpdateVarsMessage(NetworkIdentity identity) { + using var _ = sendUpdateVarsMessageMarker.Auto(); // one writer for owner, one for observers using (PooledNetworkWriter ownerWriter = NetworkWriterPool.GetWriter(), observersWriter = NetworkWriterPool.GetWriter()) {