From 23c844b2aa84a65e573dcc023d19b8f5294a8baf Mon Sep 17 00:00:00 2001 From: jhorv <38920027+jhorv@users.noreply.github.com> Date: Sat, 11 Mar 2023 15:05:48 -0500 Subject: Misc performance tweaks (#4509) * use Array.Empty() where instead of allocating new zero-length arrays * structure for loops in a way that the JIT will elide array/Span bounds checking * avoiding function calls in for loop condition tests * avoid LINQ in a hot path * conform with code style * fix mistake in GetNextWaitingObject() * fix GetNextWaitingObject() possibility of returning null if all list items have TimePoint == long.MaxValue * make GetNextWaitingObject() behave FIFO behavior for multiple items with the same TimePoint --- Ryujinx.HLE/HOS/Ipc/IpcHandleDesc.cs | 4 ++-- Ryujinx.HLE/HOS/Ipc/IpcMessage.cs | 5 +++-- Ryujinx.HLE/HOS/Kernel/Common/KTimeManager.cs | 23 ++++++++++++++++++++-- .../Time/TimeZone/TimeZoneContentManager.cs | 2 +- 4 files changed, 27 insertions(+), 7 deletions(-) (limited to 'Ryujinx.HLE/HOS') diff --git a/Ryujinx.HLE/HOS/Ipc/IpcHandleDesc.cs b/Ryujinx.HLE/HOS/Ipc/IpcHandleDesc.cs index 439590e0..e6ed4613 100644 --- a/Ryujinx.HLE/HOS/Ipc/IpcHandleDesc.cs +++ b/Ryujinx.HLE/HOS/Ipc/IpcHandleDesc.cs @@ -49,12 +49,12 @@ namespace Ryujinx.HLE.HOS.Ipc public static IpcHandleDesc MakeCopy(params int[] handles) { - return new IpcHandleDesc(handles, new int[0]); + return new IpcHandleDesc(handles, Array.Empty()); } public static IpcHandleDesc MakeMove(params int[] handles) { - return new IpcHandleDesc(new int[0], handles); + return new IpcHandleDesc(Array.Empty(), handles); } public byte[] GetBytes() diff --git a/Ryujinx.HLE/HOS/Ipc/IpcMessage.cs b/Ryujinx.HLE/HOS/Ipc/IpcMessage.cs index 09e237fe..55044da4 100644 --- a/Ryujinx.HLE/HOS/Ipc/IpcMessage.cs +++ b/Ryujinx.HLE/HOS/Ipc/IpcMessage.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; @@ -132,7 +133,7 @@ namespace Ryujinx.HLE.HOS.Ipc word0 |= (ReceiveBuff.Count & 0xf) << 24; word0 |= (ExchangeBuff.Count & 0xf) << 28; - byte[] handleData = new byte[0]; + byte[] handleData = Array.Empty(); if (HandleDesc != null) { @@ -202,7 +203,7 @@ namespace Ryujinx.HLE.HOS.Ipc word0 |= (ReceiveBuff.Count & 0xf) << 24; word0 |= (ExchangeBuff.Count & 0xf) << 28; - byte[] handleData = new byte[0]; + byte[] handleData = Array.Empty(); if (HandleDesc != null) { diff --git a/Ryujinx.HLE/HOS/Kernel/Common/KTimeManager.cs b/Ryujinx.HLE/HOS/Kernel/Common/KTimeManager.cs index 020048f4..030a314f 100644 --- a/Ryujinx.HLE/HOS/Kernel/Common/KTimeManager.cs +++ b/Ryujinx.HLE/HOS/Kernel/Common/KTimeManager.cs @@ -1,7 +1,6 @@ using Ryujinx.Common; using System; using System.Collections.Generic; -using System.Linq; using System.Threading; namespace Ryujinx.HLE.HOS.Kernel.Common @@ -86,7 +85,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Common { Interlocked.Exchange(ref _enforceWakeupFromSpinWait, 0); - next = _waitingObjects.OrderBy(x => x.TimePoint).FirstOrDefault(); + next = GetNextWaitingObject(); } if (next != null) @@ -140,6 +139,26 @@ namespace Ryujinx.HLE.HOS.Kernel.Common } } + private WaitingObject GetNextWaitingObject() + { + WaitingObject selected = null; + + long lowestTimePoint = long.MaxValue; + + for (int index = _waitingObjects.Count - 1; index >= 0; index--) + { + WaitingObject current = _waitingObjects[index]; + + if (current.TimePoint <= lowestTimePoint) + { + selected = current; + lowestTimePoint = current.TimePoint; + } + } + + return selected; + } + public static long ConvertNanosecondsToMilliseconds(long time) { time /= 1000000; diff --git a/Ryujinx.HLE/HOS/Services/Time/TimeZone/TimeZoneContentManager.cs b/Ryujinx.HLE/HOS/Services/Time/TimeZone/TimeZoneContentManager.cs index 69ed56d4..9367024e 100644 --- a/Ryujinx.HLE/HOS/Services/Time/TimeZone/TimeZoneContentManager.cs +++ b/Ryujinx.HLE/HOS/Services/Time/TimeZone/TimeZoneContentManager.cs @@ -233,7 +233,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone // If the location name is too long, error out. if (locationName.Length > 0x24) { - outLocationNameArray = new string[0]; + outLocationNameArray = Array.Empty(); return ResultCode.LocationNameTooLong; } -- cgit v1.2.3