mirror of
https://git.ryujinx.app/projects/Kenji-NX.git
synced 2026-10-07 07:28:54 +02:00
Memory changes 3
General memory improvements to decrease GC pressure and frequency. Pool big arrays and objects that are created and deleted often. Skip data copies when they aren't needed. Inline flag checks to skip unneeded allocations. From my testing the performance is about the same, but the GC frequency is much lower and collection is faster causing less and smaller spikes.
This commit is contained in:
@@ -14,6 +14,7 @@ using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap;
|
||||
using Ryujinx.HLE.HOS.Services.Nv.Types;
|
||||
using Ryujinx.Memory;
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
@@ -46,6 +47,8 @@ namespace Ryujinx.HLE.HOS.Services.Nv
|
||||
{ "/dev/nvhost-dbg-gpu", typeof(NvHostDbgGpuDeviceFile) },
|
||||
{ "/dev/nvhost-prof-gpu", typeof(NvHostProfGpuDeviceFile) },
|
||||
};
|
||||
|
||||
private static readonly ArrayPool<byte> _byteArrayPool = ArrayPool<byte>.Create();
|
||||
|
||||
public static IdDictionary DeviceFileIdRegistry = new();
|
||||
|
||||
@@ -471,10 +474,13 @@ namespace Ryujinx.HLE.HOS.Services.Nv
|
||||
|
||||
errorCode = GetIoctlArgument(context, ioctlCommand, out Span<byte> arguments);
|
||||
|
||||
if (!context.Memory.TryReadUnsafe(inlineInBufferPosition, (int)inlineInBufferSize, out Span<byte> inlineInBuffer))
|
||||
byte[] inlineInBuffer = null;
|
||||
|
||||
if (!context.Memory.TryReadUnsafe(inlineInBufferPosition, (int)inlineInBufferSize, out Span<byte> inlineInBufferSpan))
|
||||
{
|
||||
inlineInBuffer = new byte[inlineInBufferSize];
|
||||
context.Memory.Read(inlineInBufferPosition, inlineInBuffer);
|
||||
inlineInBuffer = _byteArrayPool.Rent((int)inlineInBufferSize);
|
||||
inlineInBufferSpan = inlineInBuffer;
|
||||
context.Memory.Read(inlineInBufferPosition, inlineInBufferSpan[..(int)inlineInBufferSize]);
|
||||
}
|
||||
|
||||
if (errorCode == NvResult.Success)
|
||||
@@ -483,7 +489,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv
|
||||
|
||||
if (errorCode == NvResult.Success)
|
||||
{
|
||||
NvInternalResult internalResult = deviceFile.Ioctl2(ioctlCommand, arguments, inlineInBuffer);
|
||||
NvInternalResult internalResult = deviceFile.Ioctl2(ioctlCommand, arguments, inlineInBufferSpan[..(int)inlineInBufferSize]);
|
||||
|
||||
if (internalResult == NvInternalResult.NotImplemented)
|
||||
{
|
||||
@@ -498,6 +504,11 @@ namespace Ryujinx.HLE.HOS.Services.Nv
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (inlineInBuffer is not null)
|
||||
{
|
||||
_byteArrayPool.Return(inlineInBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
context.ResponseData.Write((uint)errorCode);
|
||||
@@ -520,10 +531,13 @@ namespace Ryujinx.HLE.HOS.Services.Nv
|
||||
|
||||
errorCode = GetIoctlArgument(context, ioctlCommand, out Span<byte> arguments);
|
||||
|
||||
if (!context.Memory.TryReadUnsafe(inlineOutBufferPosition, (int)inlineOutBufferSize, out Span<byte> inlineOutBuffer))
|
||||
byte[] inlineOutBuffer = null;
|
||||
|
||||
if (!context.Memory.TryReadUnsafe(inlineOutBufferPosition, (int)inlineOutBufferSize, out Span<byte> inlineOutBufferSpan))
|
||||
{
|
||||
inlineOutBuffer = new byte[inlineOutBufferSize];
|
||||
context.Memory.Read(inlineOutBufferPosition, inlineOutBuffer);
|
||||
inlineOutBuffer = _byteArrayPool.Rent((int)inlineOutBufferSize);
|
||||
inlineOutBufferSpan = inlineOutBuffer;
|
||||
context.Memory.Read(inlineOutBufferPosition, inlineOutBufferSpan[..(int)inlineOutBufferSize]);
|
||||
}
|
||||
|
||||
if (errorCode == NvResult.Success)
|
||||
@@ -532,7 +546,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv
|
||||
|
||||
if (errorCode == NvResult.Success)
|
||||
{
|
||||
NvInternalResult internalResult = deviceFile.Ioctl3(ioctlCommand, arguments, inlineOutBuffer);
|
||||
NvInternalResult internalResult = deviceFile.Ioctl3(ioctlCommand, arguments, inlineOutBufferSpan[..(int)inlineOutBufferSize]);
|
||||
|
||||
if (internalResult == NvInternalResult.NotImplemented)
|
||||
{
|
||||
@@ -544,10 +558,15 @@ namespace Ryujinx.HLE.HOS.Services.Nv
|
||||
if ((ioctlCommand.DirectionValue & NvIoctl.Direction.Write) != 0)
|
||||
{
|
||||
context.Memory.Write(context.Request.GetBufferType0x22(0).Position, arguments.ToArray());
|
||||
context.Memory.Write(inlineOutBufferPosition, inlineOutBuffer.ToArray());
|
||||
context.Memory.Write(inlineOutBufferPosition, inlineOutBufferSpan[..(int)inlineOutBufferSize].ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (inlineOutBuffer is not null)
|
||||
{
|
||||
_byteArrayPool.Return(inlineOutBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
context.ResponseData.Write((uint)errorCode);
|
||||
|
||||
Reference in New Issue
Block a user