Ryujinx/Ryujinx.HLE/HOS/Ipc/IpcMessage.cs

284 lines
8.4 KiB
C#
Raw Normal View History

using Microsoft.IO;
using Ryujinx.Common;
using Ryujinx.Common.Memory;
using System;
using System.Buffers;
2018-02-04 18:08:20 -05:00
using System.Collections.Generic;
using System.Diagnostics;
2018-02-04 18:08:20 -05:00
using System.IO;
namespace Ryujinx.HLE.HOS.Ipc
2018-02-04 18:08:20 -05:00
{
class IpcMessage
{
public IpcMessageType Type { get; set; }
public IpcHandleDesc HandleDesc { get; set; }
public List<IpcPtrBuffDesc> PtrBuff { get; private set; }
public List<IpcBuffDesc> SendBuff { get; private set; }
public List<IpcBuffDesc> ReceiveBuff { get; private set; }
public List<IpcBuffDesc> ExchangeBuff { get; private set; }
public List<IpcRecvListBuffDesc> RecvListBuff { get; private set; }
2018-02-04 18:08:20 -05:00
public List<int> ObjectIds { get; private set; }
2018-02-04 18:08:20 -05:00
public byte[] RawData { get; set; }
public IpcMessage()
{
Reducing Memory Allocations 202303 (#4624) * use ArrayPool, avoid 6000-7000 allocs/sec of runtime * use ArrayPool, avoid ~7k allocs/second during game execution * use ArrayPool, avoid ~3000 allocs/sec during game execution * use MemoryPool, reduce 0.5 MB/sec of new allocations during game execution * avoid over-allocation by setting List<> Capacity when known * remove LINQ in KTimeManager.UnscheduleFutureInvocation * KTimeManager - avoid spinning one more time when the time has arrived * KTimeManager - let SpinWait decide when to Thread.Yield(), and don't SpinOnce() immediately after Thread.Yield() * use MemoryPool, reduce ~175k bytes/sec allocation during game execution * IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array * Make ButtonMappingEntry a record struct to avoid allocations. Set the List<ButtonMappingEntry> capacity according to use. * add MemoryBuffer type for working with MemoryPool<byte> * update changes to use MemoryBuffer * make parameter ReadOnlySpan instead of Span * whitespace fix * Revert "IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array" This reverts commit f2c698bdf65f049e8481c9f2ec7138d9b9a8261d. * tweak KTimeManager spin behavior * replace MemoryBuffer with ByteMemoryPool modeled after System.Buffers.ArrayMemoryPool<T> * make ByteMemoryPoolBuffer responsible for renting memory
2023-04-23 22:06:23 -04:00
PtrBuff = new List<IpcPtrBuffDesc>(0);
SendBuff = new List<IpcBuffDesc>(0);
ReceiveBuff = new List<IpcBuffDesc>(0);
ExchangeBuff = new List<IpcBuffDesc>(0);
RecvListBuff = new List<IpcRecvListBuffDesc>(0);
2018-02-04 18:08:20 -05:00
Reducing Memory Allocations 202303 (#4624) * use ArrayPool, avoid 6000-7000 allocs/sec of runtime * use ArrayPool, avoid ~7k allocs/second during game execution * use ArrayPool, avoid ~3000 allocs/sec during game execution * use MemoryPool, reduce 0.5 MB/sec of new allocations during game execution * avoid over-allocation by setting List<> Capacity when known * remove LINQ in KTimeManager.UnscheduleFutureInvocation * KTimeManager - avoid spinning one more time when the time has arrived * KTimeManager - let SpinWait decide when to Thread.Yield(), and don't SpinOnce() immediately after Thread.Yield() * use MemoryPool, reduce ~175k bytes/sec allocation during game execution * IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array * Make ButtonMappingEntry a record struct to avoid allocations. Set the List<ButtonMappingEntry> capacity according to use. * add MemoryBuffer type for working with MemoryPool<byte> * update changes to use MemoryBuffer * make parameter ReadOnlySpan instead of Span * whitespace fix * Revert "IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array" This reverts commit f2c698bdf65f049e8481c9f2ec7138d9b9a8261d. * tweak KTimeManager spin behavior * replace MemoryBuffer with ByteMemoryPool modeled after System.Buffers.ArrayMemoryPool<T> * make ByteMemoryPoolBuffer responsible for renting memory
2023-04-23 22:06:23 -04:00
ObjectIds = new List<int>(0);
2018-02-04 18:08:20 -05:00
}
Reducing Memory Allocations 202303 (#4624) * use ArrayPool, avoid 6000-7000 allocs/sec of runtime * use ArrayPool, avoid ~7k allocs/second during game execution * use ArrayPool, avoid ~3000 allocs/sec during game execution * use MemoryPool, reduce 0.5 MB/sec of new allocations during game execution * avoid over-allocation by setting List<> Capacity when known * remove LINQ in KTimeManager.UnscheduleFutureInvocation * KTimeManager - avoid spinning one more time when the time has arrived * KTimeManager - let SpinWait decide when to Thread.Yield(), and don't SpinOnce() immediately after Thread.Yield() * use MemoryPool, reduce ~175k bytes/sec allocation during game execution * IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array * Make ButtonMappingEntry a record struct to avoid allocations. Set the List<ButtonMappingEntry> capacity according to use. * add MemoryBuffer type for working with MemoryPool<byte> * update changes to use MemoryBuffer * make parameter ReadOnlySpan instead of Span * whitespace fix * Revert "IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array" This reverts commit f2c698bdf65f049e8481c9f2ec7138d9b9a8261d. * tweak KTimeManager spin behavior * replace MemoryBuffer with ByteMemoryPool modeled after System.Buffers.ArrayMemoryPool<T> * make ByteMemoryPoolBuffer responsible for renting memory
2023-04-23 22:06:23 -04:00
public IpcMessage(ReadOnlySpan<byte> data, long cmdPtr)
2018-02-04 18:08:20 -05:00
{
using (RecyclableMemoryStream ms = MemoryStreamManager.Shared.GetStream(data))
2018-02-04 18:08:20 -05:00
{
BinaryReader reader = new BinaryReader(ms);
2018-02-04 18:08:20 -05:00
Reducing Memory Allocations 202303 (#4624) * use ArrayPool, avoid 6000-7000 allocs/sec of runtime * use ArrayPool, avoid ~7k allocs/second during game execution * use ArrayPool, avoid ~3000 allocs/sec during game execution * use MemoryPool, reduce 0.5 MB/sec of new allocations during game execution * avoid over-allocation by setting List<> Capacity when known * remove LINQ in KTimeManager.UnscheduleFutureInvocation * KTimeManager - avoid spinning one more time when the time has arrived * KTimeManager - let SpinWait decide when to Thread.Yield(), and don't SpinOnce() immediately after Thread.Yield() * use MemoryPool, reduce ~175k bytes/sec allocation during game execution * IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array * Make ButtonMappingEntry a record struct to avoid allocations. Set the List<ButtonMappingEntry> capacity according to use. * add MemoryBuffer type for working with MemoryPool<byte> * update changes to use MemoryBuffer * make parameter ReadOnlySpan instead of Span * whitespace fix * Revert "IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array" This reverts commit f2c698bdf65f049e8481c9f2ec7138d9b9a8261d. * tweak KTimeManager spin behavior * replace MemoryBuffer with ByteMemoryPool modeled after System.Buffers.ArrayMemoryPool<T> * make ByteMemoryPoolBuffer responsible for renting memory
2023-04-23 22:06:23 -04:00
int word0 = reader.ReadInt32();
int word1 = reader.ReadInt32();
2018-02-04 18:08:20 -05:00
Reducing Memory Allocations 202303 (#4624) * use ArrayPool, avoid 6000-7000 allocs/sec of runtime * use ArrayPool, avoid ~7k allocs/second during game execution * use ArrayPool, avoid ~3000 allocs/sec during game execution * use MemoryPool, reduce 0.5 MB/sec of new allocations during game execution * avoid over-allocation by setting List<> Capacity when known * remove LINQ in KTimeManager.UnscheduleFutureInvocation * KTimeManager - avoid spinning one more time when the time has arrived * KTimeManager - let SpinWait decide when to Thread.Yield(), and don't SpinOnce() immediately after Thread.Yield() * use MemoryPool, reduce ~175k bytes/sec allocation during game execution * IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array * Make ButtonMappingEntry a record struct to avoid allocations. Set the List<ButtonMappingEntry> capacity according to use. * add MemoryBuffer type for working with MemoryPool<byte> * update changes to use MemoryBuffer * make parameter ReadOnlySpan instead of Span * whitespace fix * Revert "IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array" This reverts commit f2c698bdf65f049e8481c9f2ec7138d9b9a8261d. * tweak KTimeManager spin behavior * replace MemoryBuffer with ByteMemoryPool modeled after System.Buffers.ArrayMemoryPool<T> * make ByteMemoryPoolBuffer responsible for renting memory
2023-04-23 22:06:23 -04:00
Type = (IpcMessageType)(word0 & 0xffff);
2018-02-04 18:08:20 -05:00
Reducing Memory Allocations 202303 (#4624) * use ArrayPool, avoid 6000-7000 allocs/sec of runtime * use ArrayPool, avoid ~7k allocs/second during game execution * use ArrayPool, avoid ~3000 allocs/sec during game execution * use MemoryPool, reduce 0.5 MB/sec of new allocations during game execution * avoid over-allocation by setting List<> Capacity when known * remove LINQ in KTimeManager.UnscheduleFutureInvocation * KTimeManager - avoid spinning one more time when the time has arrived * KTimeManager - let SpinWait decide when to Thread.Yield(), and don't SpinOnce() immediately after Thread.Yield() * use MemoryPool, reduce ~175k bytes/sec allocation during game execution * IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array * Make ButtonMappingEntry a record struct to avoid allocations. Set the List<ButtonMappingEntry> capacity according to use. * add MemoryBuffer type for working with MemoryPool<byte> * update changes to use MemoryBuffer * make parameter ReadOnlySpan instead of Span * whitespace fix * Revert "IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array" This reverts commit f2c698bdf65f049e8481c9f2ec7138d9b9a8261d. * tweak KTimeManager spin behavior * replace MemoryBuffer with ByteMemoryPool modeled after System.Buffers.ArrayMemoryPool<T> * make ByteMemoryPoolBuffer responsible for renting memory
2023-04-23 22:06:23 -04:00
int ptrBuffCount = (word0 >> 16) & 0xf;
int sendBuffCount = (word0 >> 20) & 0xf;
int recvBuffCount = (word0 >> 24) & 0xf;
int xchgBuffCount = (word0 >> 28) & 0xf;
2018-02-04 18:08:20 -05:00
Reducing Memory Allocations 202303 (#4624) * use ArrayPool, avoid 6000-7000 allocs/sec of runtime * use ArrayPool, avoid ~7k allocs/second during game execution * use ArrayPool, avoid ~3000 allocs/sec during game execution * use MemoryPool, reduce 0.5 MB/sec of new allocations during game execution * avoid over-allocation by setting List<> Capacity when known * remove LINQ in KTimeManager.UnscheduleFutureInvocation * KTimeManager - avoid spinning one more time when the time has arrived * KTimeManager - let SpinWait decide when to Thread.Yield(), and don't SpinOnce() immediately after Thread.Yield() * use MemoryPool, reduce ~175k bytes/sec allocation during game execution * IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array * Make ButtonMappingEntry a record struct to avoid allocations. Set the List<ButtonMappingEntry> capacity according to use. * add MemoryBuffer type for working with MemoryPool<byte> * update changes to use MemoryBuffer * make parameter ReadOnlySpan instead of Span * whitespace fix * Revert "IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array" This reverts commit f2c698bdf65f049e8481c9f2ec7138d9b9a8261d. * tweak KTimeManager spin behavior * replace MemoryBuffer with ByteMemoryPool modeled after System.Buffers.ArrayMemoryPool<T> * make ByteMemoryPoolBuffer responsible for renting memory
2023-04-23 22:06:23 -04:00
int rawDataSize = (word1 >> 0) & 0x3ff;
int recvListFlags = (word1 >> 10) & 0xf;
bool hndDescEnable = ((word1 >> 31) & 0x1) != 0;
2018-02-04 18:08:20 -05:00
Reducing Memory Allocations 202303 (#4624) * use ArrayPool, avoid 6000-7000 allocs/sec of runtime * use ArrayPool, avoid ~7k allocs/second during game execution * use ArrayPool, avoid ~3000 allocs/sec during game execution * use MemoryPool, reduce 0.5 MB/sec of new allocations during game execution * avoid over-allocation by setting List<> Capacity when known * remove LINQ in KTimeManager.UnscheduleFutureInvocation * KTimeManager - avoid spinning one more time when the time has arrived * KTimeManager - let SpinWait decide when to Thread.Yield(), and don't SpinOnce() immediately after Thread.Yield() * use MemoryPool, reduce ~175k bytes/sec allocation during game execution * IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array * Make ButtonMappingEntry a record struct to avoid allocations. Set the List<ButtonMappingEntry> capacity according to use. * add MemoryBuffer type for working with MemoryPool<byte> * update changes to use MemoryBuffer * make parameter ReadOnlySpan instead of Span * whitespace fix * Revert "IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array" This reverts commit f2c698bdf65f049e8481c9f2ec7138d9b9a8261d. * tweak KTimeManager spin behavior * replace MemoryBuffer with ByteMemoryPool modeled after System.Buffers.ArrayMemoryPool<T> * make ByteMemoryPoolBuffer responsible for renting memory
2023-04-23 22:06:23 -04:00
if (hndDescEnable)
{
HandleDesc = new IpcHandleDesc(reader);
}
2018-02-04 18:08:20 -05:00
Reducing Memory Allocations 202303 (#4624) * use ArrayPool, avoid 6000-7000 allocs/sec of runtime * use ArrayPool, avoid ~7k allocs/second during game execution * use ArrayPool, avoid ~3000 allocs/sec during game execution * use MemoryPool, reduce 0.5 MB/sec of new allocations during game execution * avoid over-allocation by setting List<> Capacity when known * remove LINQ in KTimeManager.UnscheduleFutureInvocation * KTimeManager - avoid spinning one more time when the time has arrived * KTimeManager - let SpinWait decide when to Thread.Yield(), and don't SpinOnce() immediately after Thread.Yield() * use MemoryPool, reduce ~175k bytes/sec allocation during game execution * IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array * Make ButtonMappingEntry a record struct to avoid allocations. Set the List<ButtonMappingEntry> capacity according to use. * add MemoryBuffer type for working with MemoryPool<byte> * update changes to use MemoryBuffer * make parameter ReadOnlySpan instead of Span * whitespace fix * Revert "IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array" This reverts commit f2c698bdf65f049e8481c9f2ec7138d9b9a8261d. * tweak KTimeManager spin behavior * replace MemoryBuffer with ByteMemoryPool modeled after System.Buffers.ArrayMemoryPool<T> * make ByteMemoryPoolBuffer responsible for renting memory
2023-04-23 22:06:23 -04:00
PtrBuff = new List<IpcPtrBuffDesc>(ptrBuffCount);
2018-02-04 18:08:20 -05:00
Reducing Memory Allocations 202303 (#4624) * use ArrayPool, avoid 6000-7000 allocs/sec of runtime * use ArrayPool, avoid ~7k allocs/second during game execution * use ArrayPool, avoid ~3000 allocs/sec during game execution * use MemoryPool, reduce 0.5 MB/sec of new allocations during game execution * avoid over-allocation by setting List<> Capacity when known * remove LINQ in KTimeManager.UnscheduleFutureInvocation * KTimeManager - avoid spinning one more time when the time has arrived * KTimeManager - let SpinWait decide when to Thread.Yield(), and don't SpinOnce() immediately after Thread.Yield() * use MemoryPool, reduce ~175k bytes/sec allocation during game execution * IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array * Make ButtonMappingEntry a record struct to avoid allocations. Set the List<ButtonMappingEntry> capacity according to use. * add MemoryBuffer type for working with MemoryPool<byte> * update changes to use MemoryBuffer * make parameter ReadOnlySpan instead of Span * whitespace fix * Revert "IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array" This reverts commit f2c698bdf65f049e8481c9f2ec7138d9b9a8261d. * tweak KTimeManager spin behavior * replace MemoryBuffer with ByteMemoryPool modeled after System.Buffers.ArrayMemoryPool<T> * make ByteMemoryPoolBuffer responsible for renting memory
2023-04-23 22:06:23 -04:00
for (int index = 0; index < ptrBuffCount; index++)
{
PtrBuff.Add(new IpcPtrBuffDesc(reader));
}
2018-02-04 18:08:20 -05:00
Reducing Memory Allocations 202303 (#4624) * use ArrayPool, avoid 6000-7000 allocs/sec of runtime * use ArrayPool, avoid ~7k allocs/second during game execution * use ArrayPool, avoid ~3000 allocs/sec during game execution * use MemoryPool, reduce 0.5 MB/sec of new allocations during game execution * avoid over-allocation by setting List<> Capacity when known * remove LINQ in KTimeManager.UnscheduleFutureInvocation * KTimeManager - avoid spinning one more time when the time has arrived * KTimeManager - let SpinWait decide when to Thread.Yield(), and don't SpinOnce() immediately after Thread.Yield() * use MemoryPool, reduce ~175k bytes/sec allocation during game execution * IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array * Make ButtonMappingEntry a record struct to avoid allocations. Set the List<ButtonMappingEntry> capacity according to use. * add MemoryBuffer type for working with MemoryPool<byte> * update changes to use MemoryBuffer * make parameter ReadOnlySpan instead of Span * whitespace fix * Revert "IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array" This reverts commit f2c698bdf65f049e8481c9f2ec7138d9b9a8261d. * tweak KTimeManager spin behavior * replace MemoryBuffer with ByteMemoryPool modeled after System.Buffers.ArrayMemoryPool<T> * make ByteMemoryPoolBuffer responsible for renting memory
2023-04-23 22:06:23 -04:00
static List<IpcBuffDesc> ReadBuff(BinaryReader reader, int count)
2018-02-04 18:08:20 -05:00
{
Reducing Memory Allocations 202303 (#4624) * use ArrayPool, avoid 6000-7000 allocs/sec of runtime * use ArrayPool, avoid ~7k allocs/second during game execution * use ArrayPool, avoid ~3000 allocs/sec during game execution * use MemoryPool, reduce 0.5 MB/sec of new allocations during game execution * avoid over-allocation by setting List<> Capacity when known * remove LINQ in KTimeManager.UnscheduleFutureInvocation * KTimeManager - avoid spinning one more time when the time has arrived * KTimeManager - let SpinWait decide when to Thread.Yield(), and don't SpinOnce() immediately after Thread.Yield() * use MemoryPool, reduce ~175k bytes/sec allocation during game execution * IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array * Make ButtonMappingEntry a record struct to avoid allocations. Set the List<ButtonMappingEntry> capacity according to use. * add MemoryBuffer type for working with MemoryPool<byte> * update changes to use MemoryBuffer * make parameter ReadOnlySpan instead of Span * whitespace fix * Revert "IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array" This reverts commit f2c698bdf65f049e8481c9f2ec7138d9b9a8261d. * tweak KTimeManager spin behavior * replace MemoryBuffer with ByteMemoryPool modeled after System.Buffers.ArrayMemoryPool<T> * make ByteMemoryPoolBuffer responsible for renting memory
2023-04-23 22:06:23 -04:00
List<IpcBuffDesc> buff = new List<IpcBuffDesc>(count);
for (int index = 0; index < count; index++)
{
buff.Add(new IpcBuffDesc(reader));
}
return buff;
2018-02-04 18:08:20 -05:00
}
Reducing Memory Allocations 202303 (#4624) * use ArrayPool, avoid 6000-7000 allocs/sec of runtime * use ArrayPool, avoid ~7k allocs/second during game execution * use ArrayPool, avoid ~3000 allocs/sec during game execution * use MemoryPool, reduce 0.5 MB/sec of new allocations during game execution * avoid over-allocation by setting List<> Capacity when known * remove LINQ in KTimeManager.UnscheduleFutureInvocation * KTimeManager - avoid spinning one more time when the time has arrived * KTimeManager - let SpinWait decide when to Thread.Yield(), and don't SpinOnce() immediately after Thread.Yield() * use MemoryPool, reduce ~175k bytes/sec allocation during game execution * IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array * Make ButtonMappingEntry a record struct to avoid allocations. Set the List<ButtonMappingEntry> capacity according to use. * add MemoryBuffer type for working with MemoryPool<byte> * update changes to use MemoryBuffer * make parameter ReadOnlySpan instead of Span * whitespace fix * Revert "IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array" This reverts commit f2c698bdf65f049e8481c9f2ec7138d9b9a8261d. * tweak KTimeManager spin behavior * replace MemoryBuffer with ByteMemoryPool modeled after System.Buffers.ArrayMemoryPool<T> * make ByteMemoryPoolBuffer responsible for renting memory
2023-04-23 22:06:23 -04:00
SendBuff = ReadBuff(reader, sendBuffCount);
ReceiveBuff = ReadBuff(reader, recvBuffCount);
ExchangeBuff = ReadBuff(reader, xchgBuffCount);
2018-02-04 18:08:20 -05:00
Reducing Memory Allocations 202303 (#4624) * use ArrayPool, avoid 6000-7000 allocs/sec of runtime * use ArrayPool, avoid ~7k allocs/second during game execution * use ArrayPool, avoid ~3000 allocs/sec during game execution * use MemoryPool, reduce 0.5 MB/sec of new allocations during game execution * avoid over-allocation by setting List<> Capacity when known * remove LINQ in KTimeManager.UnscheduleFutureInvocation * KTimeManager - avoid spinning one more time when the time has arrived * KTimeManager - let SpinWait decide when to Thread.Yield(), and don't SpinOnce() immediately after Thread.Yield() * use MemoryPool, reduce ~175k bytes/sec allocation during game execution * IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array * Make ButtonMappingEntry a record struct to avoid allocations. Set the List<ButtonMappingEntry> capacity according to use. * add MemoryBuffer type for working with MemoryPool<byte> * update changes to use MemoryBuffer * make parameter ReadOnlySpan instead of Span * whitespace fix * Revert "IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array" This reverts commit f2c698bdf65f049e8481c9f2ec7138d9b9a8261d. * tweak KTimeManager spin behavior * replace MemoryBuffer with ByteMemoryPool modeled after System.Buffers.ArrayMemoryPool<T> * make ByteMemoryPoolBuffer responsible for renting memory
2023-04-23 22:06:23 -04:00
rawDataSize *= 4;
2018-02-04 18:08:20 -05:00
Reducing Memory Allocations 202303 (#4624) * use ArrayPool, avoid 6000-7000 allocs/sec of runtime * use ArrayPool, avoid ~7k allocs/second during game execution * use ArrayPool, avoid ~3000 allocs/sec during game execution * use MemoryPool, reduce 0.5 MB/sec of new allocations during game execution * avoid over-allocation by setting List<> Capacity when known * remove LINQ in KTimeManager.UnscheduleFutureInvocation * KTimeManager - avoid spinning one more time when the time has arrived * KTimeManager - let SpinWait decide when to Thread.Yield(), and don't SpinOnce() immediately after Thread.Yield() * use MemoryPool, reduce ~175k bytes/sec allocation during game execution * IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array * Make ButtonMappingEntry a record struct to avoid allocations. Set the List<ButtonMappingEntry> capacity according to use. * add MemoryBuffer type for working with MemoryPool<byte> * update changes to use MemoryBuffer * make parameter ReadOnlySpan instead of Span * whitespace fix * Revert "IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array" This reverts commit f2c698bdf65f049e8481c9f2ec7138d9b9a8261d. * tweak KTimeManager spin behavior * replace MemoryBuffer with ByteMemoryPool modeled after System.Buffers.ArrayMemoryPool<T> * make ByteMemoryPoolBuffer responsible for renting memory
2023-04-23 22:06:23 -04:00
long recvListPos = reader.BaseStream.Position + rawDataSize;
2018-02-04 18:08:20 -05:00
// Only CMIF has the padding requirements.
if (Type < IpcMessageType.TipcCloseSession)
{
long pad0 = GetPadSize16(reader.BaseStream.Position + cmdPtr);
Reducing Memory Allocations 202303 (#4624) * use ArrayPool, avoid 6000-7000 allocs/sec of runtime * use ArrayPool, avoid ~7k allocs/second during game execution * use ArrayPool, avoid ~3000 allocs/sec during game execution * use MemoryPool, reduce 0.5 MB/sec of new allocations during game execution * avoid over-allocation by setting List<> Capacity when known * remove LINQ in KTimeManager.UnscheduleFutureInvocation * KTimeManager - avoid spinning one more time when the time has arrived * KTimeManager - let SpinWait decide when to Thread.Yield(), and don't SpinOnce() immediately after Thread.Yield() * use MemoryPool, reduce ~175k bytes/sec allocation during game execution * IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array * Make ButtonMappingEntry a record struct to avoid allocations. Set the List<ButtonMappingEntry> capacity according to use. * add MemoryBuffer type for working with MemoryPool<byte> * update changes to use MemoryBuffer * make parameter ReadOnlySpan instead of Span * whitespace fix * Revert "IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array" This reverts commit f2c698bdf65f049e8481c9f2ec7138d9b9a8261d. * tweak KTimeManager spin behavior * replace MemoryBuffer with ByteMemoryPool modeled after System.Buffers.ArrayMemoryPool<T> * make ByteMemoryPoolBuffer responsible for renting memory
2023-04-23 22:06:23 -04:00
if (rawDataSize != 0)
{
rawDataSize -= (int)pad0;
}
reader.BaseStream.Seek(pad0, SeekOrigin.Current);
}
Reducing Memory Allocations 202303 (#4624) * use ArrayPool, avoid 6000-7000 allocs/sec of runtime * use ArrayPool, avoid ~7k allocs/second during game execution * use ArrayPool, avoid ~3000 allocs/sec during game execution * use MemoryPool, reduce 0.5 MB/sec of new allocations during game execution * avoid over-allocation by setting List<> Capacity when known * remove LINQ in KTimeManager.UnscheduleFutureInvocation * KTimeManager - avoid spinning one more time when the time has arrived * KTimeManager - let SpinWait decide when to Thread.Yield(), and don't SpinOnce() immediately after Thread.Yield() * use MemoryPool, reduce ~175k bytes/sec allocation during game execution * IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array * Make ButtonMappingEntry a record struct to avoid allocations. Set the List<ButtonMappingEntry> capacity according to use. * add MemoryBuffer type for working with MemoryPool<byte> * update changes to use MemoryBuffer * make parameter ReadOnlySpan instead of Span * whitespace fix * Revert "IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array" This reverts commit f2c698bdf65f049e8481c9f2ec7138d9b9a8261d. * tweak KTimeManager spin behavior * replace MemoryBuffer with ByteMemoryPool modeled after System.Buffers.ArrayMemoryPool<T> * make ByteMemoryPoolBuffer responsible for renting memory
2023-04-23 22:06:23 -04:00
int recvListCount = recvListFlags - 2;
2018-02-04 18:08:20 -05:00
Reducing Memory Allocations 202303 (#4624) * use ArrayPool, avoid 6000-7000 allocs/sec of runtime * use ArrayPool, avoid ~7k allocs/second during game execution * use ArrayPool, avoid ~3000 allocs/sec during game execution * use MemoryPool, reduce 0.5 MB/sec of new allocations during game execution * avoid over-allocation by setting List<> Capacity when known * remove LINQ in KTimeManager.UnscheduleFutureInvocation * KTimeManager - avoid spinning one more time when the time has arrived * KTimeManager - let SpinWait decide when to Thread.Yield(), and don't SpinOnce() immediately after Thread.Yield() * use MemoryPool, reduce ~175k bytes/sec allocation during game execution * IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array * Make ButtonMappingEntry a record struct to avoid allocations. Set the List<ButtonMappingEntry> capacity according to use. * add MemoryBuffer type for working with MemoryPool<byte> * update changes to use MemoryBuffer * make parameter ReadOnlySpan instead of Span * whitespace fix * Revert "IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array" This reverts commit f2c698bdf65f049e8481c9f2ec7138d9b9a8261d. * tweak KTimeManager spin behavior * replace MemoryBuffer with ByteMemoryPool modeled after System.Buffers.ArrayMemoryPool<T> * make ByteMemoryPoolBuffer responsible for renting memory
2023-04-23 22:06:23 -04:00
if (recvListCount == 0)
{
recvListCount = 1;
}
else if (recvListCount < 0)
{
recvListCount = 0;
}
2018-02-04 18:08:20 -05:00
Reducing Memory Allocations 202303 (#4624) * use ArrayPool, avoid 6000-7000 allocs/sec of runtime * use ArrayPool, avoid ~7k allocs/second during game execution * use ArrayPool, avoid ~3000 allocs/sec during game execution * use MemoryPool, reduce 0.5 MB/sec of new allocations during game execution * avoid over-allocation by setting List<> Capacity when known * remove LINQ in KTimeManager.UnscheduleFutureInvocation * KTimeManager - avoid spinning one more time when the time has arrived * KTimeManager - let SpinWait decide when to Thread.Yield(), and don't SpinOnce() immediately after Thread.Yield() * use MemoryPool, reduce ~175k bytes/sec allocation during game execution * IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array * Make ButtonMappingEntry a record struct to avoid allocations. Set the List<ButtonMappingEntry> capacity according to use. * add MemoryBuffer type for working with MemoryPool<byte> * update changes to use MemoryBuffer * make parameter ReadOnlySpan instead of Span * whitespace fix * Revert "IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array" This reverts commit f2c698bdf65f049e8481c9f2ec7138d9b9a8261d. * tweak KTimeManager spin behavior * replace MemoryBuffer with ByteMemoryPool modeled after System.Buffers.ArrayMemoryPool<T> * make ByteMemoryPoolBuffer responsible for renting memory
2023-04-23 22:06:23 -04:00
RawData = reader.ReadBytes(rawDataSize);
2018-02-04 18:08:20 -05:00
Reducing Memory Allocations 202303 (#4624) * use ArrayPool, avoid 6000-7000 allocs/sec of runtime * use ArrayPool, avoid ~7k allocs/second during game execution * use ArrayPool, avoid ~3000 allocs/sec during game execution * use MemoryPool, reduce 0.5 MB/sec of new allocations during game execution * avoid over-allocation by setting List<> Capacity when known * remove LINQ in KTimeManager.UnscheduleFutureInvocation * KTimeManager - avoid spinning one more time when the time has arrived * KTimeManager - let SpinWait decide when to Thread.Yield(), and don't SpinOnce() immediately after Thread.Yield() * use MemoryPool, reduce ~175k bytes/sec allocation during game execution * IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array * Make ButtonMappingEntry a record struct to avoid allocations. Set the List<ButtonMappingEntry> capacity according to use. * add MemoryBuffer type for working with MemoryPool<byte> * update changes to use MemoryBuffer * make parameter ReadOnlySpan instead of Span * whitespace fix * Revert "IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array" This reverts commit f2c698bdf65f049e8481c9f2ec7138d9b9a8261d. * tweak KTimeManager spin behavior * replace MemoryBuffer with ByteMemoryPool modeled after System.Buffers.ArrayMemoryPool<T> * make ByteMemoryPoolBuffer responsible for renting memory
2023-04-23 22:06:23 -04:00
reader.BaseStream.Seek(recvListPos, SeekOrigin.Begin);
2018-02-04 18:08:20 -05:00
Reducing Memory Allocations 202303 (#4624) * use ArrayPool, avoid 6000-7000 allocs/sec of runtime * use ArrayPool, avoid ~7k allocs/second during game execution * use ArrayPool, avoid ~3000 allocs/sec during game execution * use MemoryPool, reduce 0.5 MB/sec of new allocations during game execution * avoid over-allocation by setting List<> Capacity when known * remove LINQ in KTimeManager.UnscheduleFutureInvocation * KTimeManager - avoid spinning one more time when the time has arrived * KTimeManager - let SpinWait decide when to Thread.Yield(), and don't SpinOnce() immediately after Thread.Yield() * use MemoryPool, reduce ~175k bytes/sec allocation during game execution * IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array * Make ButtonMappingEntry a record struct to avoid allocations. Set the List<ButtonMappingEntry> capacity according to use. * add MemoryBuffer type for working with MemoryPool<byte> * update changes to use MemoryBuffer * make parameter ReadOnlySpan instead of Span * whitespace fix * Revert "IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array" This reverts commit f2c698bdf65f049e8481c9f2ec7138d9b9a8261d. * tweak KTimeManager spin behavior * replace MemoryBuffer with ByteMemoryPool modeled after System.Buffers.ArrayMemoryPool<T> * make ByteMemoryPoolBuffer responsible for renting memory
2023-04-23 22:06:23 -04:00
RecvListBuff = new List<IpcRecvListBuffDesc>(recvListCount);
2018-02-04 18:08:20 -05:00
Reducing Memory Allocations 202303 (#4624) * use ArrayPool, avoid 6000-7000 allocs/sec of runtime * use ArrayPool, avoid ~7k allocs/second during game execution * use ArrayPool, avoid ~3000 allocs/sec during game execution * use MemoryPool, reduce 0.5 MB/sec of new allocations during game execution * avoid over-allocation by setting List<> Capacity when known * remove LINQ in KTimeManager.UnscheduleFutureInvocation * KTimeManager - avoid spinning one more time when the time has arrived * KTimeManager - let SpinWait decide when to Thread.Yield(), and don't SpinOnce() immediately after Thread.Yield() * use MemoryPool, reduce ~175k bytes/sec allocation during game execution * IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array * Make ButtonMappingEntry a record struct to avoid allocations. Set the List<ButtonMappingEntry> capacity according to use. * add MemoryBuffer type for working with MemoryPool<byte> * update changes to use MemoryBuffer * make parameter ReadOnlySpan instead of Span * whitespace fix * Revert "IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array" This reverts commit f2c698bdf65f049e8481c9f2ec7138d9b9a8261d. * tweak KTimeManager spin behavior * replace MemoryBuffer with ByteMemoryPool modeled after System.Buffers.ArrayMemoryPool<T> * make ByteMemoryPoolBuffer responsible for renting memory
2023-04-23 22:06:23 -04:00
for (int index = 0; index < recvListCount; index++)
{
RecvListBuff.Add(new IpcRecvListBuffDesc(reader.ReadUInt64()));
}
ObjectIds = new List<int>(0);
2018-02-04 18:08:20 -05:00
}
}
public RecyclableMemoryStream GetStream(long cmdPtr, ulong recvListAddr)
2018-02-04 18:08:20 -05:00
{
RecyclableMemoryStream ms = MemoryStreamManager.Shared.GetStream();
2018-02-04 18:08:20 -05:00
int word0;
int word1;
2018-02-04 18:08:20 -05:00
word0 = (int)Type;
word0 |= (PtrBuff.Count & 0xf) << 16;
word0 |= (SendBuff.Count & 0xf) << 20;
word0 |= (ReceiveBuff.Count & 0xf) << 24;
word0 |= (ExchangeBuff.Count & 0xf) << 28;
2018-02-04 18:08:20 -05:00
using RecyclableMemoryStream handleDataStream = HandleDesc?.GetStream();
2018-02-04 18:08:20 -05:00
int dataLength = RawData?.Length ?? 0;
2018-02-04 18:08:20 -05:00
dataLength = (dataLength + 3) & ~3;
2018-02-04 18:08:20 -05:00
int rawLength = dataLength;
int pad0 = (int)GetPadSize16(cmdPtr + 8 + (handleDataStream?.Length ?? 0) + PtrBuff.Count * 8);
// Apparently, padding after Raw Data is 16 bytes, however when there is
// padding before Raw Data too, we need to subtract the size of this padding.
// This is the weirdest padding I've seen so far...
int pad1 = 0x10 - pad0;
2018-02-04 18:08:20 -05:00
dataLength = (dataLength + pad0 + pad1) / 4;
2018-02-04 18:08:20 -05:00
word1 = (dataLength & 0x3ff) | (2 << 10);
2018-02-04 18:08:20 -05:00
if (HandleDesc != null)
{
word1 |= 1 << 31;
}
2018-02-04 18:08:20 -05:00
ms.Write(word0);
ms.Write(word1);
2018-02-04 18:08:20 -05:00
if (handleDataStream != null)
{
ms.Write(handleDataStream);
}
2018-02-04 18:08:20 -05:00
foreach (IpcPtrBuffDesc ptrBuffDesc in PtrBuff)
{
ms.Write(ptrBuffDesc.GetWord0());
ms.Write(ptrBuffDesc.GetWord1());
}
ms.WriteByte(0, pad0);
2018-02-04 18:08:20 -05:00
if (RawData != null)
{
ms.Write(RawData);
ms.WriteByte(0, rawLength - RawData.Length);
}
2018-02-04 18:08:20 -05:00
ms.WriteByte(0, pad1);
2018-02-04 18:08:20 -05:00
ms.Write(recvListAddr);
ms.Position = 0;
return ms;
2018-02-04 18:08:20 -05:00
}
public RecyclableMemoryStream GetStreamTipc()
{
Debug.Assert(PtrBuff.Count == 0);
RecyclableMemoryStream ms = MemoryStreamManager.Shared.GetStream();
int word0;
int word1;
word0 = (int)Type;
word0 |= (SendBuff.Count & 0xf) << 20;
word0 |= (ReceiveBuff.Count & 0xf) << 24;
word0 |= (ExchangeBuff.Count & 0xf) << 28;
using RecyclableMemoryStream handleDataStream = HandleDesc?.GetStream();
int dataLength = RawData?.Length ?? 0;
dataLength = ((dataLength + 3) & ~3) / 4;
word1 = (dataLength & 0x3ff);
if (HandleDesc != null)
{
word1 |= 1 << 31;
}
ms.Write(word0);
ms.Write(word1);
if (handleDataStream != null)
{
ms.Write(handleDataStream);
}
if (RawData != null)
{
ms.Write(RawData);
}
return ms;
}
private long GetPadSize16(long position)
2018-02-04 18:08:20 -05:00
{
if ((position & 0xf) != 0)
2018-02-04 18:08:20 -05:00
{
return 0x10 - (position & 0xf);
2018-02-04 18:08:20 -05:00
}
return 0;
}
// ReSharper disable once InconsistentNaming
public (ulong Position, ulong Size) GetBufferType0x21(int index = 0)
{
if (PtrBuff.Count > index && PtrBuff[index].Position != 0)
{
return (PtrBuff[index].Position, PtrBuff[index].Size);
}
if (SendBuff.Count > index)
{
return (SendBuff[index].Position, SendBuff[index].Size);
}
return (0, 0);
}
// ReSharper disable once InconsistentNaming
public (ulong Position, ulong Size) GetBufferType0x22(int index = 0)
{
if (RecvListBuff.Count > index && RecvListBuff[index].Position != 0)
{
return (RecvListBuff[index].Position, RecvListBuff[index].Size);
}
if (ReceiveBuff.Count > index)
{
return (ReceiveBuff[index].Position, ReceiveBuff[index].Size);
}
return (0, 0);
}
2018-02-04 18:08:20 -05:00
}
}