minor performance improvements

This commit is contained in:
rootdarkarchon
2024-02-12 17:02:49 +01:00
committed by Loporrit
parent 0f661c9c69
commit 6f1c00041b
4 changed files with 200 additions and 199 deletions

View File

@@ -1,4 +1,5 @@
using FFXIVClientStructs.FFXIV.Client.Game.Character;
using Dalamud.Memory;
using FFXIVClientStructs.FFXIV.Client.Game.Character;
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
using MareSynchronos.Services;
using MareSynchronos.Services.Mediator;
@@ -209,7 +210,7 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase
_clearCts = null;
}
var chara = (Character*)Address;
var name = new ByteString(chara->GameObject.Name).ToString();
MemoryHelper.ReadStringNullTerminated((nint)chara->GameObject.Name, out var name);
bool nameChange = !string.Equals(name, Name, StringComparison.Ordinal);
if (nameChange)
{

View File

@@ -1,5 +1,6 @@
using Dalamud.Game.ClientState.Conditions;
using Dalamud.Game.ClientState.Objects;
using Dalamud.Memory;
using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Client.Game.Character;
using FFXIVClientStructs.FFXIV.Client.Game.Control;
@@ -386,7 +387,7 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
if (!_playerInfoCache.TryGetValue(id, out var info))
{
info.Character.ObjectId = id;
info.Character.Name = chara.Name.ToString();
MemoryHelper.ReadStringNullTerminated((nint)((GameObject*)chara.Address)->Name, out info.Character.Name);
info.Character.HomeWorldId = ((BattleChara*)chara.Address)->Character.HomeWorld;
info.Character.Address = chara.Address;
info.Hash = Crypto.GetHash256(info.Character.Name + info.Character.HomeWorldId.ToString());
@@ -399,11 +400,10 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
}
private unsafe void CheckCharacterForDrawing(PlayerCharacter p)
{
if (!IsAnythingDrawing)
{
var gameObj = (GameObject*)p.Address;
var drawObj = gameObj->DrawObject;
var playerName = p.Name;
bool isDrawing = false;
bool isDrawingChanged = false;
if ((nint)drawObj != IntPtr.Zero)
@@ -415,20 +415,20 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
if (!isDrawing)
{
isDrawing = ((CharacterBase*)drawObj)->HasModelFilesInSlotLoaded != 0;
if (isDrawing && !string.Equals(_lastGlobalBlockPlayer, p.Name, StringComparison.Ordinal)
if (isDrawing && !string.Equals(_lastGlobalBlockPlayer, playerName, StringComparison.Ordinal)
&& !string.Equals(_lastGlobalBlockReason, "HasModelFilesInSlotLoaded", StringComparison.Ordinal))
{
_lastGlobalBlockPlayer = p.Name;
_lastGlobalBlockPlayer = playerName;
_lastGlobalBlockReason = "HasModelFilesInSlotLoaded";
isDrawingChanged = true;
}
}
else
{
if (!string.Equals(_lastGlobalBlockPlayer, p.Name, StringComparison.Ordinal)
if (!string.Equals(_lastGlobalBlockPlayer, playerName, StringComparison.Ordinal)
&& !string.Equals(_lastGlobalBlockReason, "HasModelInSlotLoaded", StringComparison.Ordinal))
{
_lastGlobalBlockPlayer = p.Name;
_lastGlobalBlockPlayer = playerName;
_lastGlobalBlockReason = "HasModelInSlotLoaded";
isDrawingChanged = true;
}
@@ -436,10 +436,10 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
}
else
{
if (!string.Equals(_lastGlobalBlockPlayer, p.Name, StringComparison.Ordinal)
if (!string.Equals(_lastGlobalBlockPlayer, playerName, StringComparison.Ordinal)
&& !string.Equals(_lastGlobalBlockReason, "RenderFlags", StringComparison.Ordinal))
{
_lastGlobalBlockPlayer = p.Name;
_lastGlobalBlockPlayer = playerName;
_lastGlobalBlockReason = "RenderFlags";
isDrawingChanged = true;
}
@@ -448,12 +448,11 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
if (isDrawingChanged)
{
_logger.LogTrace("Global draw block: START => {name} ({reason})", p.Name, _lastGlobalBlockReason);
_logger.LogTrace("Global draw block: START => {name} ({reason})", playerName, _lastGlobalBlockReason);
}
IsAnythingDrawing |= isDrawing;
}
}
private void FrameworkOnUpdate(IFramework framework)
{
@@ -467,20 +466,27 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
return;
}
bool isNormalFrameworkUpdate = DateTime.Now < _delayedFrameworkUpdateCheck.AddSeconds(1);
_performanceCollector.LogPerformance(this, "FrameworkOnUpdateInternal+" + (isNormalFrameworkUpdate ? "Regular" : "Delayed"), () =>
{
IsAnythingDrawing = false;
_performanceCollector.LogPerformance(this, "ObjTableToCharas",
() =>
{
if (_sentBetweenAreas)
return;
_notUpdatedCharas.AddRange(_playerCharas.Keys);
foreach (var chara in _objectTable)
for (int i = 0; i < 200; i += 2)
{
if (chara.ObjectIndex % 2 != 0 || chara.ObjectIndex >= 200) continue;
string charaName = chara.Name.ToString();
uint homeWorldId = ((BattleChara*)chara.Address)->Character.HomeWorld;
var chara = _objectTable[i];
if (chara == null || chara.ObjectKind != Dalamud.Game.ClientState.Objects.Enums.ObjectKind.Player)
continue;
var info = GetPlayerInfo(chara);
if (!IsAnythingDrawing)
CheckCharacterForDrawing(info.Character);
_notUpdatedCharas.Remove(info.Hash);
@@ -545,7 +551,11 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
Mediator.Publish(new ResumeScanMessage(nameof(IsInCutscene)));
}
if (IsInCutscene) { Mediator.Publish(new CutsceneFrameworkUpdateMessage()); return; }
if (IsInCutscene)
{
Mediator.Publish(new CutsceneFrameworkUpdateMessage());
return;
}
if (_condition[ConditionFlag.BetweenAreas] || _condition[ConditionFlag.BetweenAreas51])
{
@@ -557,9 +567,9 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
{
_logger.LogDebug("Zone switch/Gpose start");
_sentBetweenAreas = true;
_playerInfoCache.Clear();
Mediator.Publish(new ZoneSwitchStartMessage());
Mediator.Publish(new HaltScanMessage(nameof(ConditionFlag.BetweenAreas)));
_playerInfoCache.Clear();
}
}
@@ -575,11 +585,13 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
}
if (!IsInCombat)
Mediator.Publish(new FrameworkUpdateMessage());
_performanceCollector.LogPerformance(this, "FrameworkOnUpdateInternal>MediatorFrameworkUpdate",
() => Mediator.Publish(new FrameworkUpdateMessage()));
Mediator.Publish(new PriorityFrameworkUpdateMessage());
if (DateTime.Now < _delayedFrameworkUpdateCheck.AddSeconds(1)) return;
if (isNormalFrameworkUpdate)
return;
var localPlayer = _clientState.LocalPlayer;
@@ -598,10 +610,12 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
}
if (IsInCombat)
Mediator.Publish(new FrameworkUpdateMessage());
_performanceCollector.LogPerformance(this, "FrameworkOnUpdateInternal>MediatorFrameworkUpdate",
() => Mediator.Publish(new FrameworkUpdateMessage()));
Mediator.Publish(new DelayedFrameworkUpdateMessage());
_delayedFrameworkUpdateCheck = DateTime.Now;
});
}
}

View File

@@ -130,40 +130,43 @@ public sealed class MareMediator : IHostedService
{
if (!_subscriberDict.TryGetValue(message.GetType(), out HashSet<SubscriberAction>? subscribers) || subscribers == null || !subscribers.Any()) return;
HashSet<SubscriberAction> subscribersCopy = [];
List<SubscriberAction> subscribersCopy = [];
lock (_addRemoveLock)
{
subscribersCopy = subscribers?.Where(s => s.Subscriber != null).ToHashSet() ?? [];
subscribersCopy = subscribers?.Where(s => s.Subscriber != null).ToList() ?? [];
}
foreach (SubscriberAction subscriber in subscribersCopy)
#pragma warning disable S3011 // Reflection should not be used to increase accessibility of classes, methods, or fields
GetType()
.GetMethod(nameof(ExecuteReflected), System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?
.MakeGenericMethod(message.GetType())?
.Invoke(this, [subscribersCopy, message]);
#pragma warning restore S3011 // Reflection should not be used to increase accessibility of classes, methods, or fields
}
private void ExecuteReflected<T>(List<SubscriberAction> subscribers, T message) where T : MessageBase
{
var msgTypeName = message.GetType().Name;
foreach (SubscriberAction subscriber in subscribers)
{
try
{
#pragma warning disable S3011 // Reflection should not be used to increase accessibility of classes, methods, or fields
typeof(MareMediator)
.GetMethod(nameof(ExecuteSubscriber), System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?
.MakeGenericMethod(message.GetType())
.Invoke(this, new object[] { subscriber, message });
#pragma warning restore S3011 // Reflection should not be used to increase accessibility of classes, methods, or fields
var isSameThread = message.KeepThreadContext ? "$" : string.Empty;
_performanceCollector.LogPerformance(this, $"{isSameThread}Execute>{msgTypeName}+{subscriber.Subscriber.GetType().Name}>{subscriber.Subscriber}",
() => ((Action<T>)subscriber.Action).Invoke(message));
}
catch (Exception ex)
{
if (_lastErrorTime.TryGetValue(subscriber, out var lastErrorTime) && lastErrorTime.Add(TimeSpan.FromSeconds(10)) > DateTime.UtcNow)
continue;
_logger.LogError(ex.InnerException ?? ex, "Error executing {type} for subscriber {subscriber}", message.GetType().Name, subscriber.Subscriber.GetType().Name);
_logger.LogError(ex.InnerException ?? ex, "Error executing {type} for subscriber {subscriber}",
message.GetType().Name, subscriber.Subscriber.GetType().Name);
_lastErrorTime[subscriber] = DateTime.UtcNow;
}
}
}
private void ExecuteSubscriber<T>(SubscriberAction subscriber, T message) where T : MessageBase
{
var isSameThread = message.KeepThreadContext ? "$" : string.Empty;
_performanceCollector.LogPerformance(this, $"{isSameThread}Execute>{message.GetType().Name}+{subscriber.Subscriber.GetType().Name}>{subscriber.Subscriber}", () => ((Action<T>)subscriber.Action).Invoke(message));
}
private sealed class SubscriberAction
{
public SubscriberAction(IMediatorSubscriber subscriber, object action)

View File

@@ -7,10 +7,7 @@ public static class Crypto
{
#pragma warning disable SYSLIB0021 // Type or member is obsolete
private static readonly Dictionary<string, string> _hashListSHA1 = new(StringComparer.Ordinal);
private static readonly Dictionary<string, string> _hashListSHA256 = new(StringComparer.Ordinal);
private static readonly SHA256CryptoServiceProvider _sha256CryptoProvider = new();
private static readonly SHA1CryptoServiceProvider _sha1CryptoProvider = new();
public static string GetFileHash(this string filePath)
{
@@ -18,31 +15,17 @@ public static class Crypto
return BitConverter.ToString(cryptoProvider.ComputeHash(File.ReadAllBytes(filePath))).Replace("-", "", StringComparison.Ordinal);
}
public static string GetHash(this string stringToHash)
{
return GetOrComputeHashSHA1(stringToHash);
}
public static string GetHash256(this string stringToHash)
{
return GetOrComputeHashSHA256(stringToHash);
}
private static string GetOrComputeHashSHA1(string stringToCompute)
{
if (_hashListSHA1.TryGetValue(stringToCompute, out var hash))
return hash;
return _hashListSHA1[stringToCompute] = BitConverter.ToString(_sha1CryptoProvider.ComputeHash(Encoding.UTF8.GetBytes(stringToCompute))).Replace("-", "", StringComparison.Ordinal);
}
private static string GetOrComputeHashSHA256(string stringToCompute)
{
if (_hashListSHA256.TryGetValue(stringToCompute, out var hash))
return hash;
return _hashListSHA256[stringToCompute] = BitConverter.ToString(_sha256CryptoProvider.ComputeHash(Encoding.UTF8.GetBytes(stringToCompute))).Replace("-", "", StringComparison.Ordinal);
return BitConverter.ToString(_sha256CryptoProvider.ComputeHash(Encoding.UTF8.GetBytes(stringToCompute))).Replace("-", "", StringComparison.Ordinal);
}
#pragma warning restore SYSLIB0021 // Type or member is obsolete
}