thread safety and performance improv
This commit is contained in:
@@ -105,11 +105,10 @@ public sealed class FileCacheManager : IDisposable
|
||||
|
||||
public FileCacheEntity? GetFileCacheByHash(string hash)
|
||||
{
|
||||
if (_fileCaches.Any(f => string.Equals(f.Value.Hash, hash, StringComparison.Ordinal)))
|
||||
var entry = _fileCaches.FirstOrDefault(f => string.Equals(f.Value.Hash, hash, StringComparison.Ordinal));
|
||||
if (!EqualityComparer<KeyValuePair<string, FileCacheEntity>>.Default.Equals(entry, default))
|
||||
{
|
||||
return GetValidatedFileCache(_fileCaches.Where(f => string.Equals(f.Value.Hash, hash, StringComparison.Ordinal))
|
||||
.OrderByDescending(f => f.Value.PrefixedFilePath.Length)
|
||||
.FirstOrDefault(f => string.Equals(f.Value.Hash, hash, StringComparison.Ordinal)).Value);
|
||||
return GetValidatedFileCache(entry.Value);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<Authors></Authors>
|
||||
<Company></Company>
|
||||
<Version>0.8.17</Version>
|
||||
<Version>0.8.18</Version>
|
||||
<Description></Description>
|
||||
<Copyright></Copyright>
|
||||
<PackageProjectUrl>https://github.com/Penumbra-Sync/client</PackageProjectUrl>
|
||||
|
||||
@@ -320,19 +320,6 @@ public class PlayerDataFactory
|
||||
|
||||
Stopwatch st = Stopwatch.StartNew();
|
||||
|
||||
// gather up data from ipc
|
||||
previousData.ManipulationString = _ipcManager.PenumbraGetMetaManipulations();
|
||||
previousData.HeelsOffset = _ipcManager.GetHeelsOffset();
|
||||
Task<string> getGlamourerData = _ipcManager.GlamourerGetCharacterCustomization(playerRelatedObject.Address);
|
||||
Task<string> getCustomizeData = _ipcManager.GetCustomizePlusScale();
|
||||
Task<string> getPalettePlusData = _ipcManager.PalettePlusBuildPalette();
|
||||
previousData.GlamourerString[playerRelatedObject.ObjectKind] = await getGlamourerData.ConfigureAwait(false);
|
||||
_logger.LogDebug("Glamourer is now: {data}", previousData.GlamourerString[playerRelatedObject.ObjectKind]);
|
||||
previousData.CustomizePlusScale = await getCustomizeData.ConfigureAwait(false);
|
||||
_logger.LogDebug("Customize is now: {data}", previousData.CustomizePlusScale);
|
||||
previousData.PalettePlusPalette = await getPalettePlusData.ConfigureAwait(false);
|
||||
_logger.LogDebug("Palette is now: {data}", previousData.PalettePlusPalette);
|
||||
|
||||
// gather static replacements from render model
|
||||
var (forwardResolve, reverseResolve) = BuildDataFromModel(objectKind, charaPointer, token);
|
||||
Dictionary<string, List<string>> resolvedPaths = await GetFileReplacementsFromPaths(forwardResolve, reverseResolve).ConfigureAwait(false);
|
||||
@@ -381,6 +368,19 @@ public class PlayerDataFactory
|
||||
previousData.FileReplacements[item.Key] = new HashSet<FileReplacement>(item.Value.Where(v => v.HasFileReplacement).OrderBy(v => v.ResolvedPath, StringComparer.Ordinal), FileReplacementComparer.Instance);
|
||||
}
|
||||
|
||||
// gather up data from ipc
|
||||
previousData.ManipulationString = _ipcManager.PenumbraGetMetaManipulations();
|
||||
previousData.HeelsOffset = _ipcManager.GetHeelsOffset();
|
||||
Task<string> getGlamourerData = _ipcManager.GlamourerGetCharacterCustomization(playerRelatedObject.Address);
|
||||
Task<string> getCustomizeData = _ipcManager.GetCustomizePlusScale();
|
||||
Task<string> getPalettePlusData = _ipcManager.PalettePlusBuildPalette();
|
||||
previousData.GlamourerString[playerRelatedObject.ObjectKind] = await getGlamourerData.ConfigureAwait(false);
|
||||
_logger.LogDebug("Glamourer is now: {data}", previousData.GlamourerString[playerRelatedObject.ObjectKind]);
|
||||
previousData.CustomizePlusScale = await getCustomizeData.ConfigureAwait(false);
|
||||
_logger.LogDebug("Customize is now: {data}", previousData.CustomizePlusScale);
|
||||
previousData.PalettePlusPalette = await getPalettePlusData.ConfigureAwait(false);
|
||||
_logger.LogDebug("Palette is now: {data}", previousData.PalettePlusPalette);
|
||||
|
||||
st.Stop();
|
||||
_logger.LogInformation("Building character data for {obj} took {time}ms", objectKind, TimeSpan.FromTicks(st.ElapsedTicks).TotalMilliseconds);
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ using MareSynchronos.Utils;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using GameObject = FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject;
|
||||
|
||||
namespace MareSynchronos.Services;
|
||||
@@ -53,6 +54,7 @@ public class DalamudUtilService : IHostedService
|
||||
public unsafe GameObject* GposeTarget => TargetSystem.Instance()->GPoseTarget;
|
||||
public unsafe Dalamud.Game.ClientState.Objects.Types.GameObject? GposeTargetGameObject => GposeTarget == null ? null : _objectTable[GposeTarget->ObjectIndex];
|
||||
public bool IsInCutscene { get; private set; } = false;
|
||||
public bool IsInFrameworkThread => _framework.IsInFrameworkUpdateThread;
|
||||
public bool IsInGpose { get; private set; } = false;
|
||||
public bool IsLoggedIn { get; private set; }
|
||||
public bool IsPlayerPresent => _clientState.LocalPlayer != null && _clientState.LocalPlayer.IsValid();
|
||||
@@ -146,20 +148,37 @@ public class DalamudUtilService : IHostedService
|
||||
return false;
|
||||
}
|
||||
|
||||
public async Task RunOnFrameworkThread(Action act)
|
||||
public async Task RunOnFrameworkThread(Action act, [CallerMemberName] string callerMember = "",
|
||||
[CallerFilePath] string callerFilePath = "", [CallerLineNumber] int lineNumber = 0)
|
||||
{
|
||||
_logger.LogTrace("Running Action on framework thread (FrameworkContext: {ctx}): {act}", _framework.IsInFrameworkUpdateThread, act);
|
||||
_logger.LogTrace("Running Action on framework thread (FrameworkContext: {ctx}): {member} in {file}:{line}", _framework.IsInFrameworkUpdateThread, callerMember, callerFilePath, lineNumber);
|
||||
if (!_framework.IsInFrameworkUpdateThread)
|
||||
await _framework.RunOnFrameworkThread(act).ConfigureAwait(false);
|
||||
{
|
||||
await _framework.RunOnFrameworkThread(act).ContinueWith((_) => Task.CompletedTask).ConfigureAwait(false);
|
||||
while (_framework.IsInFrameworkUpdateThread) // yield the thread again, should technically never be triggered
|
||||
{
|
||||
_logger.LogTrace("Still on framework");
|
||||
await Task.Delay(1).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
act();
|
||||
}
|
||||
|
||||
public async Task<T> RunOnFrameworkThread<T>(Func<T> func)
|
||||
public async Task<T> RunOnFrameworkThread<T>(Func<T> func, [CallerMemberName] string callerMember = "",
|
||||
[CallerFilePath] string callerFilePath = "", [CallerLineNumber] int lineNumber = 0)
|
||||
{
|
||||
_logger.LogTrace("Running Func on framework thread (FrameworkContext: {ctx}): {act}", _framework.IsInFrameworkUpdateThread, func);
|
||||
_logger.LogTrace("Running Func on framework thread (FrameworkContext: {ctx}): {member} in {file}:{line}", _framework.IsInFrameworkUpdateThread, callerMember, callerFilePath, lineNumber);
|
||||
if (!_framework.IsInFrameworkUpdateThread)
|
||||
return await _framework.RunOnFrameworkThread(func).ConfigureAwait(false);
|
||||
{
|
||||
var result = await _framework.RunOnFrameworkThread(func).ContinueWith((task) => task.Result).ConfigureAwait(false);
|
||||
while (_framework.IsInFrameworkUpdateThread) // yield the thread again, should technically never be triggered
|
||||
{
|
||||
_logger.LogTrace("Still on framework");
|
||||
await Task.Delay(1).ConfigureAwait(false);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else
|
||||
return func.Invoke();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user