Add VisibilityService to improve tick performance with many online pairs
This commit is contained in:
@@ -26,13 +26,14 @@ public class PairHandlerFactory
|
|||||||
private readonly ServerConfigurationManager _serverConfigManager;
|
private readonly ServerConfigurationManager _serverConfigManager;
|
||||||
private readonly PluginWarningNotificationService _pluginWarningNotificationManager;
|
private readonly PluginWarningNotificationService _pluginWarningNotificationManager;
|
||||||
private readonly PairAnalyzerFactory _pairAnalyzerFactory;
|
private readonly PairAnalyzerFactory _pairAnalyzerFactory;
|
||||||
|
private readonly VisibilityService _visibilityService;
|
||||||
|
|
||||||
public PairHandlerFactory(ILoggerFactory loggerFactory, GameObjectHandlerFactory gameObjectHandlerFactory, IpcManager ipcManager,
|
public PairHandlerFactory(ILoggerFactory loggerFactory, GameObjectHandlerFactory gameObjectHandlerFactory, IpcManager ipcManager,
|
||||||
FileDownloadManagerFactory fileDownloadManagerFactory, DalamudUtilService dalamudUtilService,
|
FileDownloadManagerFactory fileDownloadManagerFactory, DalamudUtilService dalamudUtilService,
|
||||||
PluginWarningNotificationService pluginWarningNotificationManager, IHostApplicationLifetime hostApplicationLifetime,
|
PluginWarningNotificationService pluginWarningNotificationManager, IHostApplicationLifetime hostApplicationLifetime,
|
||||||
FileCacheManager fileCacheManager, MareMediator mareMediator, PlayerPerformanceService playerPerformanceService,
|
FileCacheManager fileCacheManager, MareMediator mareMediator, PlayerPerformanceService playerPerformanceService,
|
||||||
ServerConfigurationManager serverConfigManager, PairAnalyzerFactory pairAnalyzerFactory,
|
ServerConfigurationManager serverConfigManager, PairAnalyzerFactory pairAnalyzerFactory,
|
||||||
MareConfigService configService)
|
MareConfigService configService, VisibilityService visibilityService)
|
||||||
{
|
{
|
||||||
_loggerFactory = loggerFactory;
|
_loggerFactory = loggerFactory;
|
||||||
_gameObjectHandlerFactory = gameObjectHandlerFactory;
|
_gameObjectHandlerFactory = gameObjectHandlerFactory;
|
||||||
@@ -47,12 +48,13 @@ public class PairHandlerFactory
|
|||||||
_serverConfigManager = serverConfigManager;
|
_serverConfigManager = serverConfigManager;
|
||||||
_pairAnalyzerFactory = pairAnalyzerFactory;
|
_pairAnalyzerFactory = pairAnalyzerFactory;
|
||||||
_configService = configService;
|
_configService = configService;
|
||||||
|
_visibilityService = visibilityService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PairHandler Create(Pair pair)
|
public PairHandler Create(Pair pair)
|
||||||
{
|
{
|
||||||
return new PairHandler(_loggerFactory.CreateLogger<PairHandler>(), pair, _pairAnalyzerFactory.Create(pair), _gameObjectHandlerFactory,
|
return new PairHandler(_loggerFactory.CreateLogger<PairHandler>(), pair, _pairAnalyzerFactory.Create(pair), _gameObjectHandlerFactory,
|
||||||
_ipcManager, _fileDownloadManagerFactory.Create(), _pluginWarningNotificationManager, _dalamudUtilService, _hostApplicationLifetime,
|
_ipcManager, _fileDownloadManagerFactory.Create(), _pluginWarningNotificationManager, _dalamudUtilService, _hostApplicationLifetime,
|
||||||
_fileCacheManager, _mareMediator, _playerPerformanceService, _serverConfigManager, _configService);
|
_fileCacheManager, _mareMediator, _playerPerformanceService, _serverConfigManager, _configService, _visibilityService);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -33,6 +33,7 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
|
|||||||
private readonly PlayerPerformanceService _playerPerformanceService;
|
private readonly PlayerPerformanceService _playerPerformanceService;
|
||||||
private readonly ServerConfigurationManager _serverConfigManager;
|
private readonly ServerConfigurationManager _serverConfigManager;
|
||||||
private readonly PluginWarningNotificationService _pluginWarningNotificationManager;
|
private readonly PluginWarningNotificationService _pluginWarningNotificationManager;
|
||||||
|
private readonly VisibilityService _visibilityService;
|
||||||
private CancellationTokenSource? _applicationCancellationTokenSource = new();
|
private CancellationTokenSource? _applicationCancellationTokenSource = new();
|
||||||
private Guid _applicationId;
|
private Guid _applicationId;
|
||||||
private Task? _applicationTask;
|
private Task? _applicationTask;
|
||||||
@@ -54,7 +55,7 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
|
|||||||
FileCacheManager fileDbManager, MareMediator mediator,
|
FileCacheManager fileDbManager, MareMediator mediator,
|
||||||
PlayerPerformanceService playerPerformanceService,
|
PlayerPerformanceService playerPerformanceService,
|
||||||
ServerConfigurationManager serverConfigManager,
|
ServerConfigurationManager serverConfigManager,
|
||||||
MareConfigService configService) : base(logger, mediator)
|
MareConfigService configService, VisibilityService visibilityService) : base(logger, mediator)
|
||||||
{
|
{
|
||||||
Pair = pair;
|
Pair = pair;
|
||||||
PairAnalyzer = pairAnalyzer;
|
PairAnalyzer = pairAnalyzer;
|
||||||
@@ -68,8 +69,12 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
|
|||||||
_playerPerformanceService = playerPerformanceService;
|
_playerPerformanceService = playerPerformanceService;
|
||||||
_serverConfigManager = serverConfigManager;
|
_serverConfigManager = serverConfigManager;
|
||||||
_configService = configService;
|
_configService = configService;
|
||||||
|
_visibilityService = visibilityService;
|
||||||
|
|
||||||
|
_visibilityService.StartTracking(Pair.Ident);
|
||||||
|
|
||||||
|
Mediator.SubscribeKeyed<PlayerVisibilityMessage>(this, Pair.Ident, (msg) => UpdateVisibility(msg.IsVisible));
|
||||||
|
|
||||||
Mediator.Subscribe<FrameworkUpdateMessage>(this, (_) => FrameworkUpdate());
|
|
||||||
Mediator.Subscribe<ZoneSwitchStartMessage>(this, (_) =>
|
Mediator.Subscribe<ZoneSwitchStartMessage>(this, (_) =>
|
||||||
{
|
{
|
||||||
_downloadCancellationTokenSource?.CancelDispose();
|
_downloadCancellationTokenSource?.CancelDispose();
|
||||||
@@ -137,7 +142,7 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
public long LastAppliedDataBytes { get; private set; }
|
public long LastAppliedDataBytes { get; private set; }
|
||||||
public Pair Pair { get; private set; }
|
public Pair Pair { get; private init; }
|
||||||
public PairAnalyzer PairAnalyzer { get; private init; }
|
public PairAnalyzer PairAnalyzer { get; private init; }
|
||||||
public nint PlayerCharacter => _charaHandler?.Address ?? nint.Zero;
|
public nint PlayerCharacter => _charaHandler?.Address ?? nint.Zero;
|
||||||
public unsafe uint PlayerCharacterId => (_charaHandler?.Address ?? nint.Zero) == nint.Zero
|
public unsafe uint PlayerCharacterId => (_charaHandler?.Address ?? nint.Zero) == nint.Zero
|
||||||
@@ -255,6 +260,8 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
|
|||||||
|
|
||||||
if (!disposing) return;
|
if (!disposing) return;
|
||||||
|
|
||||||
|
_visibilityService.StopTracking(Pair.Ident);
|
||||||
|
|
||||||
SetUploading(isUploading: false);
|
SetUploading(isUploading: false);
|
||||||
var name = PlayerName;
|
var name = PlayerName;
|
||||||
Logger.LogDebug("Disposing {name} ({user})", name, Pair);
|
Logger.LogDebug("Disposing {name} ({user})", name, Pair);
|
||||||
@@ -634,7 +641,7 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FrameworkUpdate()
|
private void UpdateVisibility(bool nowVisible)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(PlayerName))
|
if (string.IsNullOrEmpty(PlayerName))
|
||||||
{
|
{
|
||||||
@@ -647,7 +654,7 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
|
|||||||
$"Initializing User For Character {pc.Name}")));
|
$"Initializing User For Character {pc.Name}")));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_charaHandler?.Address != nint.Zero && !IsVisible)
|
if (!IsVisible && nowVisible)
|
||||||
{
|
{
|
||||||
IsVisible = true;
|
IsVisible = true;
|
||||||
Mediator.Publish(new PairHandlerVisibleMessage(this));
|
Mediator.Publish(new PairHandlerVisibleMessage(this));
|
||||||
@@ -666,10 +673,10 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
|
|||||||
Logger.LogTrace("{this} visibility changed, now: {visi}, no cached data exists", this, IsVisible);
|
Logger.LogTrace("{this} visibility changed, now: {visi}, no cached data exists", this, IsVisible);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (_charaHandler?.Address == nint.Zero && IsVisible)
|
else if (IsVisible && !nowVisible)
|
||||||
{
|
{
|
||||||
IsVisible = false;
|
IsVisible = false;
|
||||||
_charaHandler.Invalidate();
|
_charaHandler?.Invalidate();
|
||||||
_downloadCancellationTokenSource?.CancelDispose();
|
_downloadCancellationTokenSource?.CancelDispose();
|
||||||
_downloadCancellationTokenSource = null;
|
_downloadCancellationTokenSource = null;
|
||||||
Logger.LogTrace("{this} visibility changed, now: {visi}", this, IsVisible);
|
Logger.LogTrace("{this} visibility changed, now: {visi}", this, IsVisible);
|
||||||
|
|||||||
@@ -114,6 +114,7 @@ public sealed class Plugin : IDalamudPlugin
|
|||||||
collection.AddSingleton<IpcProvider>();
|
collection.AddSingleton<IpcProvider>();
|
||||||
collection.AddSingleton<PluginWatcherService>();
|
collection.AddSingleton<PluginWatcherService>();
|
||||||
collection.AddSingleton<PlayerPerformanceService>();
|
collection.AddSingleton<PlayerPerformanceService>();
|
||||||
|
collection.AddSingleton<VisibilityService>();
|
||||||
collection.AddSingleton<EventAggregator>();
|
collection.AddSingleton<EventAggregator>();
|
||||||
collection.AddSingleton<DalamudUtilService>();
|
collection.AddSingleton<DalamudUtilService>();
|
||||||
collection.AddSingleton<DtrEntry>();
|
collection.AddSingleton<DtrEntry>();
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ namespace MareSynchronos.Services;
|
|||||||
|
|
||||||
public class DalamudUtilService : IHostedService, IMediatorSubscriber
|
public class DalamudUtilService : IHostedService, IMediatorSubscriber
|
||||||
{
|
{
|
||||||
internal struct PlayerCharacter
|
public struct PlayerCharacter
|
||||||
{
|
{
|
||||||
public uint ObjectId;
|
public uint ObjectId;
|
||||||
public string Name;
|
public string Name;
|
||||||
@@ -390,7 +390,7 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
|
|||||||
return _gameGui.WorldToScreen(obj.Position, out var screenPos) ? screenPos : Vector2.Zero;
|
return _gameGui.WorldToScreen(obj.Position, out var screenPos) ? screenPos : Vector2.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal PlayerCharacter FindPlayerByNameHash(string ident)
|
public PlayerCharacter FindPlayerByNameHash(string ident)
|
||||||
{
|
{
|
||||||
_playerCharas.TryGetValue(ident, out var result);
|
_playerCharas.TryGetValue(ident, out var result);
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ public record ProfilePopoutToggle(Pair? Pair) : MessageBase;
|
|||||||
public record CompactUiChange(Vector2 Size, Vector2 Position) : MessageBase;
|
public record CompactUiChange(Vector2 Size, Vector2 Position) : MessageBase;
|
||||||
public record ProfileOpenStandaloneMessage(Pair Pair) : MessageBase;
|
public record ProfileOpenStandaloneMessage(Pair Pair) : MessageBase;
|
||||||
public record RemoveWindowMessage(WindowMediatorSubscriberBase Window) : MessageBase;
|
public record RemoveWindowMessage(WindowMediatorSubscriberBase Window) : MessageBase;
|
||||||
|
public record PlayerVisibilityMessage(string Ident, bool IsVisible) : KeyedMessage(Ident, SameThread: true);
|
||||||
public record PairHandlerVisibleMessage(PairHandler Player) : MessageBase;
|
public record PairHandlerVisibleMessage(PairHandler Player) : MessageBase;
|
||||||
public record OpenReportPopupMessage(Pair PairToReport) : MessageBase;
|
public record OpenReportPopupMessage(Pair PairToReport) : MessageBase;
|
||||||
public record OpenBanUserPopupMessage(Pair PairToBan, GroupFullInfoDto GroupFullInfoDto) : MessageBase;
|
public record OpenBanUserPopupMessage(Pair PairToBan, GroupFullInfoDto GroupFullInfoDto) : MessageBase;
|
||||||
|
|||||||
51
MareSynchronos/Services/VisibilityService.cs
Normal file
51
MareSynchronos/Services/VisibilityService.cs
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
using MareSynchronos.Services.Mediator;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
|
||||||
|
namespace MareSynchronos.Services;
|
||||||
|
|
||||||
|
// Detect when players of interest are visible
|
||||||
|
public class VisibilityService : DisposableMediatorSubscriberBase
|
||||||
|
{
|
||||||
|
private readonly DalamudUtilService _dalamudUtil;
|
||||||
|
private ConcurrentDictionary<string, bool> _trackedPlayerVisibility = new();
|
||||||
|
private ConcurrentQueue<string> _removedPlayerMessageQueue = new();
|
||||||
|
|
||||||
|
public VisibilityService(ILogger<PairAnalyzer> logger, MareMediator mediator, DalamudUtilService dalamudUtil)
|
||||||
|
: base(logger, mediator)
|
||||||
|
{
|
||||||
|
_dalamudUtil = dalamudUtil;
|
||||||
|
Mediator.Subscribe<FrameworkUpdateMessage>(this, (_) => FrameworkUpdate());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StartTracking(string ident)
|
||||||
|
{
|
||||||
|
_trackedPlayerVisibility.TryAdd(ident, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StopTracking(string ident)
|
||||||
|
{
|
||||||
|
// No PairVisibilityMessage is emitted if the player was visible when removed
|
||||||
|
_trackedPlayerVisibility.TryRemove(ident, out _);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FrameworkUpdate()
|
||||||
|
{
|
||||||
|
foreach (var player in _trackedPlayerVisibility)
|
||||||
|
{
|
||||||
|
string ident = player.Key;
|
||||||
|
var findResult = _dalamudUtil.FindPlayerByNameHash(ident);
|
||||||
|
|
||||||
|
if (!player.Value && findResult.ObjectId != 0)
|
||||||
|
{
|
||||||
|
if (_trackedPlayerVisibility.TryUpdate(ident, newValue: true, comparisonValue: false))
|
||||||
|
Mediator.Publish<PlayerVisibilityMessage>(new(ident, IsVisible: true));
|
||||||
|
}
|
||||||
|
else if (player.Value && findResult.ObjectId == 0)
|
||||||
|
{
|
||||||
|
if (_trackedPlayerVisibility.TryUpdate(ident, newValue: false, comparisonValue: true))
|
||||||
|
Mediator.Publish<PlayerVisibilityMessage>(new(ident, IsVisible: false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user