From 0c8571fba92058b8281efcea0cdb2583104bf7ce Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Mon, 20 Jan 2025 17:14:13 +0100 Subject: [PATCH] Reduce and pad IMC allocations and log allocations. --- Penumbra.GameData | 2 +- Penumbra/Collections/Cache/ImcCache.cs | 1 - Penumbra/Collections/ModCollectionIdentity.cs | 6 +++--- Penumbra/Interop/GameState.cs | 4 ++-- Penumbra/Meta/Files/ImcFile.cs | 15 ++++++++++----- Penumbra/Meta/Files/MetaBaseFile.cs | 15 +++++++++++++-- 6 files changed, 29 insertions(+), 14 deletions(-) diff --git a/Penumbra.GameData b/Penumbra.GameData index 5bac66e5..ebeea67c 160000 --- a/Penumbra.GameData +++ b/Penumbra.GameData @@ -1 +1 @@ -Subproject commit 5bac66e5ad73e57919aff7f8b046606b75e191a2 +Subproject commit ebeea67c17f6bf4ce7e635041b2138e835d31262 diff --git a/Penumbra/Collections/Cache/ImcCache.cs b/Penumbra/Collections/Cache/ImcCache.cs index 0f610d90..461ffccc 100644 --- a/Penumbra/Collections/Cache/ImcCache.cs +++ b/Penumbra/Collections/Cache/ImcCache.cs @@ -51,7 +51,6 @@ public sealed class ImcCache(MetaFileManager manager, ModCollection collection) if (!_imcFiles.TryGetValue(path, out var pair)) pair = (new ImcFile(Manager, identifier), []); - if (!Apply(pair.Item1, identifier, entry)) return; diff --git a/Penumbra/Collections/ModCollectionIdentity.cs b/Penumbra/Collections/ModCollectionIdentity.cs index c7f60005..bd2d47c4 100644 --- a/Penumbra/Collections/ModCollectionIdentity.cs +++ b/Penumbra/Collections/ModCollectionIdentity.cs @@ -10,9 +10,9 @@ public struct ModCollectionIdentity(Guid id, LocalCollectionId localId) public static readonly ModCollectionIdentity Empty = new(Guid.Empty, LocalCollectionId.Zero, EmptyCollectionName, 0); - public string Name { get; set; } - public Guid Id { get; } = id; - public LocalCollectionId LocalId { get; } = localId; + public string Name { get; set; } = string.Empty; + public Guid Id { get; } = id; + public LocalCollectionId LocalId { get; } = localId; /// The index of the collection is set and kept up-to-date by the CollectionManager. public int Index { get; internal set; } diff --git a/Penumbra/Interop/GameState.cs b/Penumbra/Interop/GameState.cs index 497be508..95cef468 100644 --- a/Penumbra/Interop/GameState.cs +++ b/Penumbra/Interop/GameState.cs @@ -11,8 +11,8 @@ public class GameState : IService { #region Last Game Object - private readonly ThreadLocal> _lastGameObject = new(() => new Queue()); - public readonly ThreadLocal CharacterAssociated = new(() => false); + private readonly ThreadLocal> _lastGameObject = new(() => new Queue()); + public readonly ThreadLocal CharacterAssociated = new(() => false); public nint LastGameObject => _lastGameObject.IsValueCreated && _lastGameObject.Value!.Count > 0 ? _lastGameObject.Value.Peek() : nint.Zero; diff --git a/Penumbra/Meta/Files/ImcFile.cs b/Penumbra/Meta/Files/ImcFile.cs index 01ef3f16..de022f4c 100644 --- a/Penumbra/Meta/Files/ImcFile.cs +++ b/Penumbra/Meta/Files/ImcFile.cs @@ -1,3 +1,4 @@ +using Penumbra.GameData; using Penumbra.GameData.Enums; using Penumbra.GameData.Structs; using Penumbra.Interop.Structs; @@ -192,22 +193,26 @@ public unsafe class ImcFile : MetaBaseFile public void Replace(ResourceHandle* resource) { var (data, length) = resource->GetData(); - if (length == ActualLength) + var actualLength = ActualLength; + if (length >= actualLength) { - MemoryUtility.MemCpyUnchecked((byte*)data, Data, ActualLength); + MemoryUtility.MemCpyUnchecked((byte*)data, Data, actualLength); + MemoryUtility.MemSet((byte*)data + actualLength, 0, length - actualLength); return; } - var newData = Manager.XivAllocator.Allocate(ActualLength, 8); + var paddedLength = actualLength.PadToMultiple(128); + var newData = Manager.XivAllocator.Allocate(paddedLength, 8); if (newData == null) { Penumbra.Log.Error($"Could not replace loaded IMC data at 0x{(ulong)resource:X}, allocation failed."); return; } - MemoryUtility.MemCpyUnchecked(newData, Data, ActualLength); + MemoryUtility.MemCpyUnchecked(newData, Data, actualLength); + MemoryUtility.MemSet((byte*)data + actualLength, 0, paddedLength - actualLength); Manager.XivAllocator.Release((void*)data, length); - resource->SetData((nint)newData, ActualLength); + resource->SetData((nint)newData, paddedLength); } } diff --git a/Penumbra/Meta/Files/MetaBaseFile.cs b/Penumbra/Meta/Files/MetaBaseFile.cs index 5bc36068..0cb34ab3 100644 --- a/Penumbra/Meta/Files/MetaBaseFile.cs +++ b/Penumbra/Meta/Files/MetaBaseFile.cs @@ -28,11 +28,16 @@ public unsafe interface IFileAllocator public sealed class MarshalAllocator : IFileAllocator { public unsafe T* Allocate(int length, int alignment = 1) where T : unmanaged - => (T*)Marshal.AllocHGlobal(length * sizeof(T)); + { + var ret = (T*)Marshal.AllocHGlobal(length * sizeof(T)); + Penumbra.Log.Verbose($"Allocating {length * sizeof(T)} bytes via Marshal Allocator to 0x{(nint)ret:X}."); + return ret; + } public unsafe void Release(ref T* pointer, int length) where T : unmanaged { Marshal.FreeHGlobal((nint)pointer); + Penumbra.Log.Verbose($"Freeing {length * sizeof(T)} bytes from 0x{(nint)pointer:X} via Marshal Allocator."); pointer = null; } } @@ -53,11 +58,17 @@ public sealed unsafe class XivFileAllocator : IFileAllocator, IService => ((delegate* unmanaged)_getFileSpaceAddress)(); public T* Allocate(int length, int alignment = 1) where T : unmanaged - => (T*)GetFileSpace()->Malloc((ulong)(length * sizeof(T)), (ulong)alignment); + { + var ret = (T*)GetFileSpace()->Malloc((ulong)(length * sizeof(T)), (ulong)alignment); + Penumbra.Log.Verbose($"Allocating {length * sizeof(T)} bytes via FFXIV File Allocator to 0x{(nint)ret:X}."); + return ret; + } public void Release(ref T* pointer, int length) where T : unmanaged { + IMemorySpace.Free(pointer, (ulong)(length * sizeof(T))); + Penumbra.Log.Verbose($"Freeing {length * sizeof(T)} bytes from 0x{(nint)pointer:X} via FFXIV File Allocator."); pointer = null; } }