From 216026c096d844f8bf09ee0e185dec4111c64095 Mon Sep 17 00:00:00 2001 From: jhorv <38920027+jhorv@users.noreply.github.com> Date: Sun, 21 Apr 2024 06:57:35 -0400 Subject: Use pooled memory and avoid memory copies (#6691) * perf: use ByteMemoryPool * feat: KPageTableBase/KPageTable new methods to read and write `ReadOnlySequence` * new: add IWritableBlock.Write(ulong, ReadOnlySequence) with default impl * perf: use GetReadOnlySequence() instead of GetSpan() * perf: make `Parcel` IDisposable, use `ByteMemoryPool` for internal allocation, and make Parcel consumers dispose of it * remove comment about copySize * remove unnecessary Clear() --- .../HOS/Kernel/Memory/KPageTableBase.cs | 36 +++++++++++++++++----- 1 file changed, 28 insertions(+), 8 deletions(-) (limited to 'src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs') diff --git a/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs b/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs index ae99a434..58bbc0db 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs @@ -5,6 +5,7 @@ using Ryujinx.Horizon.Common; using Ryujinx.Memory; using Ryujinx.Memory.Range; using System; +using System.Buffers; using System.Collections.Generic; using System.Diagnostics; @@ -1568,7 +1569,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory while (size > 0) { - ulong copySize = 0x100000; // Copy chunck size. Any value will do, moderate sizes are recommended. + ulong copySize = int.MaxValue; if (copySize > size) { @@ -1577,11 +1578,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory if (toServer) { - currentProcess.CpuMemory.Write(serverAddress, GetSpan(clientAddress, (int)copySize)); + currentProcess.CpuMemory.Write(serverAddress, GetReadOnlySequence(clientAddress, (int)copySize)); } else { - Write(clientAddress, currentProcess.CpuMemory.GetSpan(serverAddress, (int)copySize)); + Write(clientAddress, currentProcess.CpuMemory.GetReadOnlySequence(serverAddress, (int)copySize)); } serverAddress += copySize; @@ -1911,9 +1912,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory Context.Memory.Fill(GetDramAddressFromPa(dstFirstPagePa), unusedSizeBefore, (byte)_ipcFillValue); ulong copySize = addressRounded <= endAddr ? addressRounded - address : size; - var data = srcPageTable.GetSpan(addressTruncated + unusedSizeBefore, (int)copySize); + var data = srcPageTable.GetReadOnlySequence(addressTruncated + unusedSizeBefore, (int)copySize); - Context.Memory.Write(GetDramAddressFromPa(dstFirstPagePa + unusedSizeBefore), data); + ((IWritableBlock)Context.Memory).Write(GetDramAddressFromPa(dstFirstPagePa + unusedSizeBefore), data); firstPageFillAddress += unusedSizeBefore + copySize; @@ -1977,9 +1978,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory if (send) { ulong copySize = endAddr - endAddrTruncated; - var data = srcPageTable.GetSpan(endAddrTruncated, (int)copySize); + var data = srcPageTable.GetReadOnlySequence(endAddrTruncated, (int)copySize); - Context.Memory.Write(GetDramAddressFromPa(dstLastPagePa), data); + ((IWritableBlock)Context.Memory).Write(GetDramAddressFromPa(dstLastPagePa), data); lastPageFillAddr += copySize; @@ -2943,6 +2944,18 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory /// Page list where the ranges will be added protected abstract void GetPhysicalRegions(ulong va, ulong size, KPageList pageList); + /// + /// Gets a read-only sequence of data from CPU mapped memory. + /// + /// + /// Allows reading non-contiguous memory without first copying it to a newly allocated single contiguous block. + /// + /// Virtual address of the data + /// Size of the data + /// A read-only sequence of the data + /// Throw for unhandled invalid or unmapped memory accesses + protected abstract ReadOnlySequence GetReadOnlySequence(ulong va, int size); + /// /// Gets a read-only span of data from CPU mapped memory. /// @@ -2952,7 +2965,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory /// /// Virtual address of the data /// Size of the data - /// True if read tracking is triggered on the span /// A read-only span of the data /// Throw for unhandled invalid or unmapped memory accesses protected abstract ReadOnlySpan GetSpan(ulong va, int size); @@ -3060,6 +3072,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory /// Size of the region protected abstract void SignalMemoryTracking(ulong va, ulong size, bool write); + /// + /// Writes data to CPU mapped memory, with write tracking. + /// + /// Virtual address to write the data into + /// Data to be written + /// Throw for unhandled invalid or unmapped memory accesses + protected abstract void Write(ulong va, ReadOnlySequence data); + /// /// Writes data to CPU mapped memory, with write tracking. /// -- cgit v1.2.3