diff options
| author | jhorv <38920027+jhorv@users.noreply.github.com> | 2024-04-21 06:57:35 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-04-21 12:57:35 +0200 |
| commit | 216026c096d844f8bf09ee0e185dec4111c64095 (patch) | |
| tree | 222eb5476aacb79f9d67abd799ee1657c2d63e7c /src/Ryujinx.HLE/HOS/Kernel | |
| parent | 7070cf6ae502b5c11551fceb164bc9f158ba980b (diff) | |
Use pooled memory and avoid memory copies (#6691)
* perf: use ByteMemoryPool
* feat: KPageTableBase/KPageTable new methods to read and write `ReadOnlySequence<byte>`
* new: add IWritableBlock.Write(ulong, ReadOnlySequence<byte>) 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()
Diffstat (limited to 'src/Ryujinx.HLE/HOS/Kernel')
| -rw-r--r-- | src/Ryujinx.HLE/HOS/Kernel/Ipc/KServerSession.cs | 4 | ||||
| -rw-r--r-- | src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTable.cs | 13 | ||||
| -rw-r--r-- | src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs | 36 |
3 files changed, 43 insertions, 10 deletions
diff --git a/src/Ryujinx.HLE/HOS/Kernel/Ipc/KServerSession.cs b/src/Ryujinx.HLE/HOS/Kernel/Ipc/KServerSession.cs index 7e41a3f3..3b428085 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Ipc/KServerSession.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Ipc/KServerSession.cs @@ -570,7 +570,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc } else { - serverProcess.CpuMemory.Write(copyDst, clientProcess.CpuMemory.GetSpan(copySrc, (int)copySize)); + serverProcess.CpuMemory.Write(copyDst, clientProcess.CpuMemory.GetReadOnlySequence(copySrc, (int)copySize)); } if (clientResult != Result.Success) @@ -858,7 +858,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc } else { - clientProcess.CpuMemory.Write(copyDst, serverProcess.CpuMemory.GetSpan(copySrc, (int)copySize)); + clientProcess.CpuMemory.Write(copyDst, serverProcess.CpuMemory.GetReadOnlySequence(copySrc, (int)copySize)); } } diff --git a/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTable.cs b/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTable.cs index d262c159..4ffa447d 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTable.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTable.cs @@ -2,6 +2,7 @@ using Ryujinx.Horizon.Common; using Ryujinx.Memory; using Ryujinx.Memory.Range; using System; +using System.Buffers; using System.Collections.Generic; using System.Diagnostics; @@ -35,6 +36,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory } /// <inheritdoc/> + protected override ReadOnlySequence<byte> GetReadOnlySequence(ulong va, int size) + { + return _cpuMemory.GetReadOnlySequence(va, size); + } + + /// <inheritdoc/> protected override ReadOnlySpan<byte> GetSpan(ulong va, int size) { return _cpuMemory.GetSpan(va, size); @@ -248,6 +255,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory } /// <inheritdoc/> + protected override void Write(ulong va, ReadOnlySequence<byte> data) + { + _cpuMemory.Write(va, data); + } + + /// <inheritdoc/> protected override void Write(ulong va, ReadOnlySpan<byte> data) { _cpuMemory.Write(va, data); 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; @@ -2944,6 +2945,18 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory protected abstract void GetPhysicalRegions(ulong va, ulong size, KPageList pageList); /// <summary> + /// Gets a read-only sequence of data from CPU mapped memory. + /// </summary> + /// <remarks> + /// Allows reading non-contiguous memory without first copying it to a newly allocated single contiguous block. + /// </remarks> + /// <param name="va">Virtual address of the data</param> + /// <param name="size">Size of the data</param> + /// <returns>A read-only sequence of the data</returns> + /// <exception cref="Ryujinx.Memory.InvalidMemoryRegionException">Throw for unhandled invalid or unmapped memory accesses</exception> + protected abstract ReadOnlySequence<byte> GetReadOnlySequence(ulong va, int size); + + /// <summary> /// Gets a read-only span of data from CPU mapped memory. /// </summary> /// <remarks> @@ -2952,7 +2965,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory /// </remarks> /// <param name="va">Virtual address of the data</param> /// <param name="size">Size of the data</param> - /// <param name="tracked">True if read tracking is triggered on the span</param> /// <returns>A read-only span of the data</returns> /// <exception cref="Ryujinx.Memory.InvalidMemoryRegionException">Throw for unhandled invalid or unmapped memory accesses</exception> protected abstract ReadOnlySpan<byte> GetSpan(ulong va, int size); @@ -3066,6 +3078,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory /// <param name="va">Virtual address to write the data into</param> /// <param name="data">Data to be written</param> /// <exception cref="Ryujinx.Memory.InvalidMemoryRegionException">Throw for unhandled invalid or unmapped memory accesses</exception> + protected abstract void Write(ulong va, ReadOnlySequence<byte> data); + + /// <summary> + /// Writes data to CPU mapped memory, with write tracking. + /// </summary> + /// <param name="va">Virtual address to write the data into</param> + /// <param name="data">Data to be written</param> + /// <exception cref="Ryujinx.Memory.InvalidMemoryRegionException">Throw for unhandled invalid or unmapped memory accesses</exception> protected abstract void Write(ulong va, ReadOnlySpan<byte> data); } } |
