Skip to content

Commit

Permalink
Reduce and pad IMC allocations and log allocations.
Browse files Browse the repository at this point in the history
  • Loading branch information
Ottermandias committed Jan 20, 2025
1 parent 8779f4b commit 0c8571f
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 14 deletions.
2 changes: 1 addition & 1 deletion Penumbra.GameData
1 change: 0 additions & 1 deletion Penumbra/Collections/Cache/ImcCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ private void ApplyFile(ImcIdentifier identifier, ImcEntry entry)
if (!_imcFiles.TryGetValue(path, out var pair))
pair = (new ImcFile(Manager, identifier), []);


if (!Apply(pair.Item1, identifier, entry))
return;

Expand Down
6 changes: 3 additions & 3 deletions Penumbra/Collections/ModCollectionIdentity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/// <summary> The index of the collection is set and kept up-to-date by the CollectionManager. </summary>
public int Index { get; internal set; }
Expand Down
4 changes: 2 additions & 2 deletions Penumbra/Interop/GameState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ public class GameState : IService
{
#region Last Game Object

private readonly ThreadLocal<Queue<nint>> _lastGameObject = new(() => new Queue<nint>());
public readonly ThreadLocal<bool> CharacterAssociated = new(() => false);
private readonly ThreadLocal<Queue<nint>> _lastGameObject = new(() => new Queue<nint>());
public readonly ThreadLocal<bool> CharacterAssociated = new(() => false);

public nint LastGameObject
=> _lastGameObject.IsValueCreated && _lastGameObject.Value!.Count > 0 ? _lastGameObject.Value.Peek() : nint.Zero;
Expand Down
15 changes: 10 additions & 5 deletions Penumbra/Meta/Files/ImcFile.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Penumbra.GameData;
using Penumbra.GameData.Enums;
using Penumbra.GameData.Structs;
using Penumbra.Interop.Structs;
Expand Down Expand Up @@ -192,22 +193,26 @@ public static ImcEntry GetEntry(ReadOnlySpan<byte> imcFileData, EquipSlot slot,
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);
}
}
15 changes: 13 additions & 2 deletions Penumbra/Meta/Files/MetaBaseFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,16 @@ public void Release(void* pointer, int length)
public sealed class MarshalAllocator : IFileAllocator
{
public unsafe T* Allocate<T>(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<T>(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;
}
}
Expand All @@ -53,11 +58,17 @@ public XivFileAllocator(IGameInteropProvider provider)
=> ((delegate* unmanaged<IMemorySpace*>)_getFileSpaceAddress)();

public T* Allocate<T>(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<T>(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;
}
}
Expand Down

0 comments on commit 0c8571f

Please sign in to comment.