mirror of
https://git.ryujinx.app/projects/Kenji-NX.git
synced 2026-10-04 03:38:51 +02:00
Memory Changes part 2
* Slightly refactors RangeLists from the last Memory Changes MR, which fixes issue 61. * Convert as many const size array iterators to span iterators as possible. When iterating over a const size array, every iteration created a Span, now only the first iteration does in most places. * Now using object pooling for a few object types that were rapidly deleted and recreated. * Converted a few flag checks to binary operations to save memory allocations.
This commit is contained in:
@@ -580,7 +580,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||
{
|
||||
KThread selectedSuggestedCore = context.Schedulers[suggestedCore]._state.SelectedThread;
|
||||
|
||||
if (selectedSuggestedCore == suggested || (selectedSuggestedCore != null && selectedSuggestedCore.DynamicPriority < 2))
|
||||
if (selectedSuggestedCore == suggested || selectedSuggestedCore is { DynamicPriority: < 2 })
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using ARMeilleure.State;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Cpu;
|
||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||
@@ -658,17 +659,20 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||
const int MaxFpuRegistersAArch32 = 16;
|
||||
|
||||
ThreadContext context = new();
|
||||
|
||||
Span<ulong> registersSpan = context.Registers.AsSpan();
|
||||
Span<V128> fpuRegistersSpan = context.FpuRegisters.AsSpan();
|
||||
|
||||
if (Owner.Flags.HasFlag(ProcessCreationFlags.Is64Bit))
|
||||
{
|
||||
for (int i = 0; i < context.Registers.Length; i++)
|
||||
for (int i = 0; i < registersSpan.Length; i++)
|
||||
{
|
||||
context.Registers[i] = Context.GetX(i);
|
||||
registersSpan[i] = Context.GetX(i);
|
||||
}
|
||||
|
||||
for (int i = 0; i < context.FpuRegisters.Length; i++)
|
||||
for (int i = 0; i < fpuRegistersSpan.Length; i++)
|
||||
{
|
||||
context.FpuRegisters[i] = Context.GetV(i);
|
||||
fpuRegistersSpan[i] = Context.GetV(i);
|
||||
}
|
||||
|
||||
context.Fp = Context.GetX(29);
|
||||
@@ -682,12 +686,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||
{
|
||||
for (int i = 0; i < MaxRegistersAArch32; i++)
|
||||
{
|
||||
context.Registers[i] = (uint)Context.GetX(i);
|
||||
registersSpan[i] = (uint)Context.GetX(i);
|
||||
}
|
||||
|
||||
for (int i = 0; i < MaxFpuRegistersAArch32; i++)
|
||||
{
|
||||
context.FpuRegisters[i] = Context.GetV(i);
|
||||
fpuRegistersSpan[i] = Context.GetV(i);
|
||||
}
|
||||
|
||||
context.Pc = (uint)Context.Pc;
|
||||
|
||||
@@ -75,17 +75,21 @@ namespace Ryujinx.HLE.HOS.Services.Fatal
|
||||
{
|
||||
errorReport.AppendLine("\tStackTrace:");
|
||||
|
||||
Span<ulong> stackTraceSpan = cpuContext64.StackTrace.AsSpan();
|
||||
|
||||
for (int i = 0; i < cpuContext64.StackTraceSize; i++)
|
||||
{
|
||||
errorReport.AppendLine($"\t\t0x{cpuContext64.StackTrace[i]:x16}");
|
||||
errorReport.AppendLine($"\t\t0x{stackTraceSpan[i]:x16}");
|
||||
}
|
||||
}
|
||||
|
||||
errorReport.AppendLine("\tRegisters:");
|
||||
|
||||
Span<ulong> xSpan = cpuContext64.X.AsSpan();
|
||||
|
||||
for (int i = 0; i < cpuContext64.X.Length; i++)
|
||||
for (int i = 0; i < xSpan.Length; i++)
|
||||
{
|
||||
errorReport.AppendLine($"\t\tX[{i:d2}]:\t0x{cpuContext64.X[i]:x16}");
|
||||
errorReport.AppendLine($"\t\tX[{i:d2}]:\t0x{xSpan[i]:x16}");
|
||||
}
|
||||
|
||||
errorReport.AppendLine();
|
||||
@@ -109,18 +113,22 @@ namespace Ryujinx.HLE.HOS.Services.Fatal
|
||||
if (cpuContext32.StackTraceSize > 0)
|
||||
{
|
||||
errorReport.AppendLine("\tStackTrace:");
|
||||
|
||||
Span<uint> stackTraceSpan = cpuContext32.StackTrace.AsSpan();
|
||||
|
||||
for (int i = 0; i < cpuContext32.StackTraceSize; i++)
|
||||
{
|
||||
errorReport.AppendLine($"\t\t0x{cpuContext32.StackTrace[i]:x16}");
|
||||
errorReport.AppendLine($"\t\t0x{stackTraceSpan[i]:x16}");
|
||||
}
|
||||
}
|
||||
|
||||
errorReport.AppendLine("\tRegisters:");
|
||||
|
||||
Span<uint> xSpan = cpuContext32.X.AsSpan();
|
||||
|
||||
for (int i = 0; i < cpuContext32.X.Length; i++)
|
||||
for (int i = 0; i < xSpan.Length; i++)
|
||||
{
|
||||
errorReport.AppendLine($"\t\tX[{i:d2}]:\t0x{cpuContext32.X[i]:x16}");
|
||||
errorReport.AppendLine($"\t\tX[{i:d2}]:\t0x{xSpan[i]:x16}");
|
||||
}
|
||||
|
||||
errorReport.AppendLine();
|
||||
|
||||
@@ -94,6 +94,8 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
||||
primaryIndex = PlayerIndex.Unknown;
|
||||
configuredCount = 0;
|
||||
|
||||
Span<NpadState> nPadsSpan = _device.Hid.SharedMemory.Npads.AsSpan();
|
||||
|
||||
for (int i = 0; i < MaxControllers; ++i)
|
||||
{
|
||||
ControllerType npad = _configuredTypes[i];
|
||||
@@ -103,7 +105,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
||||
continue;
|
||||
}
|
||||
|
||||
ControllerType currentType = (ControllerType)_device.Hid.SharedMemory.Npads[i].InternalState.StyleSet;
|
||||
ControllerType currentType = (ControllerType)nPadsSpan[i].InternalState.StyleSet;
|
||||
|
||||
if (currentType != ControllerType.None && (npad & acceptedTypes) != 0 && _supportedPlayers[i])
|
||||
{
|
||||
|
||||
@@ -23,12 +23,14 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
||||
{
|
||||
newState.TouchesCount = points.Length;
|
||||
|
||||
int pointsLength = Math.Min(points.Length, newState.Touches.Length);
|
||||
Span<TouchState> touchesSpan = newState.Touches.AsSpan();
|
||||
|
||||
int pointsLength = Math.Min(points.Length, touchesSpan.Length);
|
||||
|
||||
for (int i = 0; i < pointsLength; ++i)
|
||||
{
|
||||
TouchPoint pi = points[i];
|
||||
newState.Touches[i] = new TouchState
|
||||
touchesSpan[i] = new TouchState
|
||||
{
|
||||
DeltaTime = newState.SamplingNumber,
|
||||
Attribute = pi.Attribute,
|
||||
|
||||
@@ -49,12 +49,14 @@ namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common
|
||||
}
|
||||
|
||||
ulong index = ReadCurrentIndex();
|
||||
|
||||
Span<AtomicStorage<T>> storageSpan = _storage.AsSpan();
|
||||
|
||||
while (true)
|
||||
{
|
||||
int inputEntryIndex = (int)((index + MaxEntries + 1 - countAvailaible) % MaxEntries);
|
||||
|
||||
ref AtomicStorage<T> result = ref _storage[inputEntryIndex];
|
||||
ref AtomicStorage<T> result = ref storageSpan[inputEntryIndex];
|
||||
|
||||
ulong samplingNumber0 = result.ReadSamplingNumberAtomic();
|
||||
ulong samplingNumber1 = result.ReadSamplingNumberAtomic();
|
||||
@@ -91,15 +93,17 @@ namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common
|
||||
ulong index = ReadCurrentIndex();
|
||||
|
||||
AtomicStorage<T>[] result = new AtomicStorage<T>[countAvailaible];
|
||||
|
||||
Span<AtomicStorage<T>> storageSpan = _storage.AsSpan();
|
||||
|
||||
for (ulong i = 0; i < countAvailaible; i++)
|
||||
{
|
||||
int inputEntryIndex = (int)((index + MaxEntries + 1 - countAvailaible + i) % MaxEntries);
|
||||
int outputEntryIndex = (int)(countAvailaible - i - 1);
|
||||
|
||||
ulong samplingNumber0 = _storage[inputEntryIndex].ReadSamplingNumberAtomic();
|
||||
result[outputEntryIndex] = _storage[inputEntryIndex];
|
||||
ulong samplingNumber1 = _storage[inputEntryIndex].ReadSamplingNumberAtomic();
|
||||
ulong samplingNumber0 = storageSpan[inputEntryIndex].ReadSamplingNumberAtomic();
|
||||
result[outputEntryIndex] = storageSpan[inputEntryIndex];
|
||||
ulong samplingNumber1 = storageSpan[inputEntryIndex].ReadSamplingNumberAtomic();
|
||||
|
||||
if (samplingNumber0 != samplingNumber1 && (i > 0 && (result[outputEntryIndex].SamplingNumber - result[outputEntryIndex].SamplingNumber) != 1))
|
||||
{
|
||||
|
||||
@@ -5,6 +5,7 @@ using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Keyboard;
|
||||
using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Mouse;
|
||||
using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad;
|
||||
using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.TouchScreen;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory
|
||||
@@ -54,10 +55,12 @@ namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory
|
||||
Mouse = RingLifo<MouseState>.Create(),
|
||||
Keyboard = RingLifo<KeyboardState>.Create(),
|
||||
};
|
||||
|
||||
Span<NpadState> npadsSpan = result.Npads.AsSpan();
|
||||
|
||||
for (int i = 0; i < result.Npads.Length; i++)
|
||||
for (int i = 0; i < npadsSpan.Length; i++)
|
||||
{
|
||||
result.Npads[i] = NpadState.Create();
|
||||
npadsSpan[i] = NpadState.Create();
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Ryujinx.Common.Memory;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
@@ -19,20 +20,24 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.Types
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
Span<NodeLatestUpdate> arraySpan = array.AsSpan();
|
||||
Span<NodeInfo> beforeNodesSpan = beforeNodes.AsSpan();
|
||||
Span<NodeInfo> afterNodesSpan = afterNodes.AsSpan();
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (beforeNodes[i].IsConnected == 0)
|
||||
if (beforeNodesSpan[i].IsConnected == 0)
|
||||
{
|
||||
if (afterNodes[i].IsConnected != 0)
|
||||
if (afterNodesSpan[i].IsConnected != 0)
|
||||
{
|
||||
array[i].State |= NodeLatestUpdateFlags.Connect;
|
||||
arraySpan[i].State |= NodeLatestUpdateFlags.Connect;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (afterNodes[i].IsConnected == 0)
|
||||
if (afterNodesSpan[i].IsConnected == 0)
|
||||
{
|
||||
array[i].State |= NodeLatestUpdateFlags.Disconnect;
|
||||
arraySpan[i].State |= NodeLatestUpdateFlags.Disconnect;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,14 +50,16 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.Types
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
Span<NodeLatestUpdate> arraySpan = array.AsSpan();
|
||||
|
||||
for (int i = 0; i < number; i++)
|
||||
{
|
||||
result[i].Reserved = new Array7<byte>();
|
||||
|
||||
if (i < LdnConst.NodeCountMax)
|
||||
{
|
||||
result[i].State = array[i].State;
|
||||
array[i].State = NodeLatestUpdateFlags.None;
|
||||
result[i].State = arraySpan[i].State;
|
||||
arraySpan[i].State = NodeLatestUpdateFlags.None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,9 +77,11 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnMitm
|
||||
},
|
||||
};
|
||||
|
||||
Span<NodeInfo> nodesSpan = networkInfo.Ldn.Nodes.AsSpan();
|
||||
|
||||
for (int i = 0; i < LdnConst.NodeCountMax; i++)
|
||||
{
|
||||
networkInfo.Ldn.Nodes[i] = new NodeInfo
|
||||
nodesSpan[i] = new NodeInfo
|
||||
{
|
||||
MacAddress = new Array6<byte>(),
|
||||
UserName = new Array33<byte>(),
|
||||
@@ -229,11 +231,13 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnMitm
|
||||
NetworkInfo.Common.Ssid = _fakeSsid;
|
||||
|
||||
NetworkInfo.Ldn.Nodes = new Array8<NodeInfo>();
|
||||
|
||||
Span<NodeInfo> nodesSpan = NetworkInfo.Ldn.Nodes.AsSpan();
|
||||
|
||||
for (int i = 0; i < LdnConst.NodeCountMax; i++)
|
||||
{
|
||||
NetworkInfo.Ldn.Nodes[i].NodeId = (byte)i;
|
||||
NetworkInfo.Ldn.Nodes[i].IsConnected = 0;
|
||||
nodesSpan[i].NodeId = (byte)i;
|
||||
nodesSpan[i].IsConnected = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -408,11 +412,11 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnMitm
|
||||
|
||||
private int LocateEmptyNode()
|
||||
{
|
||||
Array8<NodeInfo> nodes = NetworkInfo.Ldn.Nodes;
|
||||
Span<NodeInfo> nodesSpan = NetworkInfo.Ldn.Nodes.AsSpan();
|
||||
|
||||
for (int i = 1; i < nodes.Length; i++)
|
||||
for (int i = 1; i < nodesSpan.Length; i++)
|
||||
{
|
||||
if (nodes[i].IsConnected == 0)
|
||||
if (nodesSpan[i].IsConnected == 0)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
|
||||
@@ -335,9 +335,11 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu
|
||||
writeEntries = (uint)_pageSizes.Length;
|
||||
}
|
||||
|
||||
Span<VaRegion> regionsSpan = arguments.Regions.AsSpan();
|
||||
|
||||
for (uint i = 0; i < writeEntries; i++)
|
||||
{
|
||||
ref var region = ref arguments.Regions[(int)i];
|
||||
ref var region = ref regionsSpan[(int)i];
|
||||
|
||||
var vmRegion = _vmRegions[i];
|
||||
uint pageSize = _pageSizes[i];
|
||||
|
||||
@@ -30,21 +30,21 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Sfdnsres.Types
|
||||
{
|
||||
Port = IPAddress.HostToNetworkOrder(Port);
|
||||
|
||||
RawIpv4AddressNetworkEndianSwap(ref Address);
|
||||
RawIpv4AddressNetworkEndianSwap(Address.AsSpan());
|
||||
}
|
||||
|
||||
public void ToHostOrder()
|
||||
{
|
||||
Port = IPAddress.NetworkToHostOrder(Port);
|
||||
|
||||
RawIpv4AddressNetworkEndianSwap(ref Address);
|
||||
RawIpv4AddressNetworkEndianSwap(Address.AsSpan());
|
||||
}
|
||||
|
||||
public static void RawIpv4AddressNetworkEndianSwap(ref Array4<byte> address)
|
||||
public static void RawIpv4AddressNetworkEndianSwap(Span<byte> address)
|
||||
{
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
address.AsSpan().Reverse();
|
||||
address.Reverse();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Sfdnsres.Types
|
||||
{
|
||||
// Nintendo hardcode 4 bytes in that case here.
|
||||
Array4<byte> address = MemoryMarshal.Read<Array4<byte>>(buffer);
|
||||
AddrInfo4.RawIpv4AddressNetworkEndianSwap(ref address);
|
||||
AddrInfo4.RawIpv4AddressNetworkEndianSwap(address.AsSpan());
|
||||
|
||||
rawIPv4Address = address;
|
||||
|
||||
@@ -115,7 +115,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Sfdnsres.Types
|
||||
else
|
||||
{
|
||||
Array4<byte> rawIPv4Address = RawIPv4Address.Value;
|
||||
AddrInfo4.RawIpv4AddressNetworkEndianSwap(ref rawIPv4Address);
|
||||
AddrInfo4.RawIpv4AddressNetworkEndianSwap(rawIPv4Address.AsSpan());
|
||||
|
||||
MemoryMarshal.Write(buffer, in rawIPv4Address);
|
||||
|
||||
|
||||
@@ -60,10 +60,10 @@ namespace Ryujinx.HLE.UI.Input
|
||||
|
||||
public void Update(bool supressEvents = false)
|
||||
{
|
||||
ref var npads = ref _device.Hid.SharedMemory.Npads;
|
||||
int npadsCount = _device.Hid.SharedMemory.Npads.Length;
|
||||
|
||||
// Process each input individually.
|
||||
for (int npadIndex = 0; npadIndex < npads.Length; npadIndex++)
|
||||
for (int npadIndex = 0; npadIndex < npadsCount; npadIndex++)
|
||||
{
|
||||
UpdateNpad(npadIndex, supressEvents);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user