aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Audio/Renderer/Server
diff options
context:
space:
mode:
authorjhorv <38920027+jhorv@users.noreply.github.com>2023-04-23 22:06:23 -0400
committerGitHub <noreply@github.com>2023-04-24 02:06:23 +0000
commit666e05f5cb9aa9dc86874823c108586e7a5b38bd (patch)
tree0f4c2cf207e0c73c98c29148edc4cb9393a9e357 /Ryujinx.Audio/Renderer/Server
parent8d9d508dc78eb5225c99cb425fa484999f3c4305 (diff)
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
Diffstat (limited to 'Ryujinx.Audio/Renderer/Server')
-rw-r--r--Ryujinx.Audio/Renderer/Server/StateUpdater.cs9
-rw-r--r--Ryujinx.Audio/Renderer/Server/Voice/VoiceState.cs4
2 files changed, 10 insertions, 3 deletions
diff --git a/Ryujinx.Audio/Renderer/Server/StateUpdater.cs b/Ryujinx.Audio/Renderer/Server/StateUpdater.cs
index 0446cd8c..5cf539c6 100644
--- a/Ryujinx.Audio/Renderer/Server/StateUpdater.cs
+++ b/Ryujinx.Audio/Renderer/Server/StateUpdater.cs
@@ -11,6 +11,7 @@ using Ryujinx.Audio.Renderer.Server.Voice;
using Ryujinx.Audio.Renderer.Utils;
using Ryujinx.Common.Logging;
using System;
+using System.Buffers;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@@ -149,12 +150,16 @@ namespace Ryujinx.Audio.Renderer.Server
state.InUse = false;
}
+ Memory<VoiceUpdateState>[] voiceUpdateStatesArray = ArrayPool<Memory<VoiceUpdateState>>.Shared.Rent(Constants.VoiceChannelCountMax);
+
+ Span<Memory<VoiceUpdateState>> voiceUpdateStates = voiceUpdateStatesArray.AsSpan(0, Constants.VoiceChannelCountMax);
+
// Start processing
for (int i = 0; i < context.GetCount(); i++)
{
VoiceInParameter parameter = parameters[i];
- Memory<VoiceUpdateState>[] voiceUpdateStates = new Memory<VoiceUpdateState>[Constants.VoiceChannelCountMax];
+ voiceUpdateStates.Fill(Memory<VoiceUpdateState>.Empty);
ref VoiceOutStatus outStatus = ref SpanIOHelper.GetWriteRef<VoiceOutStatus>(ref _output)[0];
@@ -197,6 +202,8 @@ namespace Ryujinx.Audio.Renderer.Server
}
}
+ ArrayPool<Memory<VoiceUpdateState>>.Shared.Return(voiceUpdateStatesArray);
+
int currentOutputSize = _output.Length;
OutputHeader.VoicesSize = (uint)(Unsafe.SizeOf<VoiceOutStatus>() * context.GetCount());
diff --git a/Ryujinx.Audio/Renderer/Server/Voice/VoiceState.cs b/Ryujinx.Audio/Renderer/Server/Voice/VoiceState.cs
index 006d6dd3..0bf53c54 100644
--- a/Ryujinx.Audio/Renderer/Server/Voice/VoiceState.cs
+++ b/Ryujinx.Audio/Renderer/Server/Voice/VoiceState.cs
@@ -378,7 +378,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
/// <param name="outStatus">The given user output.</param>
/// <param name="parameter">The user parameter.</param>
/// <param name="voiceUpdateStates">The voice states associated to the <see cref="VoiceState"/>.</param>
- public void WriteOutStatus(ref VoiceOutStatus outStatus, ref VoiceInParameter parameter, Memory<VoiceUpdateState>[] voiceUpdateStates)
+ public void WriteOutStatus(ref VoiceOutStatus outStatus, ref VoiceInParameter parameter, ReadOnlySpan<Memory<VoiceUpdateState>> voiceUpdateStates)
{
#if DEBUG
// Sanity check in debug mode of the internal state
@@ -424,7 +424,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
/// <param name="voiceUpdateStates">The voice states associated to the <see cref="VoiceState"/>.</param>
/// <param name="mapper">The mapper to use.</param>
/// <param name="behaviourContext">The behaviour context.</param>
- public void UpdateWaveBuffers(out ErrorInfo[] errorInfos, ref VoiceInParameter parameter, Memory<VoiceUpdateState>[] voiceUpdateStates, ref PoolMapper mapper, ref BehaviourContext behaviourContext)
+ public void UpdateWaveBuffers(out ErrorInfo[] errorInfos, ref VoiceInParameter parameter, ReadOnlySpan<Memory<VoiceUpdateState>> voiceUpdateStates, ref PoolMapper mapper, ref BehaviourContext behaviourContext)
{
errorInfos = new ErrorInfo[Constants.VoiceWaveBufferCount * 2];