mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 18:27:24 +01:00
Reduce and pad IMC allocations and log allocations.
This commit is contained in:
parent
8779f4b689
commit
0c8571fba9
6 changed files with 29 additions and 14 deletions
|
|
@ -1 +1 @@
|
||||||
Subproject commit 5bac66e5ad73e57919aff7f8b046606b75e191a2
|
Subproject commit ebeea67c17f6bf4ce7e635041b2138e835d31262
|
||||||
|
|
@ -51,7 +51,6 @@ public sealed class ImcCache(MetaFileManager manager, ModCollection collection)
|
||||||
if (!_imcFiles.TryGetValue(path, out var pair))
|
if (!_imcFiles.TryGetValue(path, out var pair))
|
||||||
pair = (new ImcFile(Manager, identifier), []);
|
pair = (new ImcFile(Manager, identifier), []);
|
||||||
|
|
||||||
|
|
||||||
if (!Apply(pair.Item1, identifier, entry))
|
if (!Apply(pair.Item1, identifier, entry))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,9 @@ public struct ModCollectionIdentity(Guid id, LocalCollectionId localId)
|
||||||
|
|
||||||
public static readonly ModCollectionIdentity Empty = new(Guid.Empty, LocalCollectionId.Zero, EmptyCollectionName, 0);
|
public static readonly ModCollectionIdentity Empty = new(Guid.Empty, LocalCollectionId.Zero, EmptyCollectionName, 0);
|
||||||
|
|
||||||
public string Name { get; set; }
|
public string Name { get; set; } = string.Empty;
|
||||||
public Guid Id { get; } = id;
|
public Guid Id { get; } = id;
|
||||||
public LocalCollectionId LocalId { get; } = localId;
|
public LocalCollectionId LocalId { get; } = localId;
|
||||||
|
|
||||||
/// <summary> The index of the collection is set and kept up-to-date by the CollectionManager. </summary>
|
/// <summary> The index of the collection is set and kept up-to-date by the CollectionManager. </summary>
|
||||||
public int Index { get; internal set; }
|
public int Index { get; internal set; }
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,8 @@ public class GameState : IService
|
||||||
{
|
{
|
||||||
#region Last Game Object
|
#region Last Game Object
|
||||||
|
|
||||||
private readonly ThreadLocal<Queue<nint>> _lastGameObject = new(() => new Queue<nint>());
|
private readonly ThreadLocal<Queue<nint>> _lastGameObject = new(() => new Queue<nint>());
|
||||||
public readonly ThreadLocal<bool> CharacterAssociated = new(() => false);
|
public readonly ThreadLocal<bool> CharacterAssociated = new(() => false);
|
||||||
|
|
||||||
public nint LastGameObject
|
public nint LastGameObject
|
||||||
=> _lastGameObject.IsValueCreated && _lastGameObject.Value!.Count > 0 ? _lastGameObject.Value.Peek() : nint.Zero;
|
=> _lastGameObject.IsValueCreated && _lastGameObject.Value!.Count > 0 ? _lastGameObject.Value.Peek() : nint.Zero;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
using Penumbra.GameData;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
using Penumbra.GameData.Structs;
|
using Penumbra.GameData.Structs;
|
||||||
using Penumbra.Interop.Structs;
|
using Penumbra.Interop.Structs;
|
||||||
|
|
@ -192,22 +193,26 @@ public unsafe class ImcFile : MetaBaseFile
|
||||||
public void Replace(ResourceHandle* resource)
|
public void Replace(ResourceHandle* resource)
|
||||||
{
|
{
|
||||||
var (data, length) = resource->GetData();
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var newData = Manager.XivAllocator.Allocate(ActualLength, 8);
|
var paddedLength = actualLength.PadToMultiple(128);
|
||||||
|
var newData = Manager.XivAllocator.Allocate(paddedLength, 8);
|
||||||
if (newData == null)
|
if (newData == null)
|
||||||
{
|
{
|
||||||
Penumbra.Log.Error($"Could not replace loaded IMC data at 0x{(ulong)resource:X}, allocation failed.");
|
Penumbra.Log.Error($"Could not replace loaded IMC data at 0x{(ulong)resource:X}, allocation failed.");
|
||||||
return;
|
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);
|
Manager.XivAllocator.Release((void*)data, length);
|
||||||
resource->SetData((nint)newData, ActualLength);
|
resource->SetData((nint)newData, paddedLength);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,11 +28,16 @@ public unsafe interface IFileAllocator
|
||||||
public sealed class MarshalAllocator : IFileAllocator
|
public sealed class MarshalAllocator : IFileAllocator
|
||||||
{
|
{
|
||||||
public unsafe T* Allocate<T>(int length, int alignment = 1) where T : unmanaged
|
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
|
public unsafe void Release<T>(ref T* pointer, int length) where T : unmanaged
|
||||||
{
|
{
|
||||||
Marshal.FreeHGlobal((nint)pointer);
|
Marshal.FreeHGlobal((nint)pointer);
|
||||||
|
Penumbra.Log.Verbose($"Freeing {length * sizeof(T)} bytes from 0x{(nint)pointer:X} via Marshal Allocator.");
|
||||||
pointer = null;
|
pointer = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -53,11 +58,17 @@ public sealed unsafe class XivFileAllocator : IFileAllocator, IService
|
||||||
=> ((delegate* unmanaged<IMemorySpace*>)_getFileSpaceAddress)();
|
=> ((delegate* unmanaged<IMemorySpace*>)_getFileSpaceAddress)();
|
||||||
|
|
||||||
public T* Allocate<T>(int length, int alignment = 1) where T : unmanaged
|
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
|
public void Release<T>(ref T* pointer, int length) where T : unmanaged
|
||||||
{
|
{
|
||||||
|
|
||||||
IMemorySpace.Free(pointer, (ulong)(length * sizeof(T)));
|
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;
|
pointer = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue