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
This commit is contained in:
jhorv 2023-03-11 15:05:48 -05:00 committed by GitHub
parent 81691b9e37
commit 23c844b2aa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 48 additions and 31 deletions

View file

@ -265,7 +265,7 @@ namespace ARMeilleure.CodeGen.Arm64
} }
else else
{ {
relocInfo = new RelocInfo(new RelocEntry[0]); relocInfo = new RelocInfo(Array.Empty<RelocEntry>());
} }
return (code, relocInfo); return (code, relocInfo);

View file

@ -433,16 +433,11 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
private static int GetHighestValueIndex(Span<int> span) private static int GetHighestValueIndex(Span<int> span)
{ {
int highest = span[0]; int highest = int.MinValue;
if (highest == int.MaxValue)
{
return 0;
}
int selected = 0; int selected = 0;
for (int index = 1; index < span.Length; index++) for (int index = 0; index < span.Length; index++)
{ {
int current = span[index]; int current = span[index];

View file

@ -17,7 +17,7 @@ namespace ARMeilleure.Decoders
{ {
uint[] tbl = new uint[256]; uint[] tbl = new uint[256];
for (int idx = 0; idx < 256; idx++) for (int idx = 0; idx < tbl.Length; idx++)
{ {
tbl[idx] = ExpandImm8ToFP32((uint)idx); tbl[idx] = ExpandImm8ToFP32((uint)idx);
} }
@ -29,7 +29,7 @@ namespace ARMeilleure.Decoders
{ {
ulong[] tbl = new ulong[256]; ulong[] tbl = new ulong[256];
for (int idx = 0; idx < 256; idx++) for (int idx = 0; idx < tbl.Length; idx++)
{ {
tbl[idx] = ExpandImm8ToFP64((ulong)idx); tbl[idx] = ExpandImm8ToFP64((ulong)idx);
} }

View file

@ -1301,7 +1301,7 @@ namespace ARMeilleure.Decoders
{ {
List<InstInfo>[] temp = new List<InstInfo>[FastLookupSize]; List<InstInfo>[] temp = new List<InstInfo>[FastLookupSize];
for (int index = 0; index < FastLookupSize; index++) for (int index = 0; index < temp.Length; index++)
{ {
temp[index] = new List<InstInfo>(); temp[index] = new List<InstInfo>();
} }
@ -1311,7 +1311,7 @@ namespace ARMeilleure.Decoders
int mask = ToFastLookupIndex(inst.Mask); int mask = ToFastLookupIndex(inst.Mask);
int value = ToFastLookupIndex(inst.Value); int value = ToFastLookupIndex(inst.Value);
for (int index = 0; index < FastLookupSize; index++) for (int index = 0; index < temp.Length; index++)
{ {
if ((index & mask) == value) if ((index & mask) == value)
{ {
@ -1320,7 +1320,7 @@ namespace ARMeilleure.Decoders
} }
} }
for (int index = 0; index < FastLookupSize; index++) for (int index = 0; index < temp.Length; index++)
{ {
table[index] = temp[index].ToArray(); table[index] = temp[index].ToArray();
} }

View file

@ -400,7 +400,9 @@ namespace Ryujinx.Audio.Common
{ {
uint bufferIndex = (_releasedBufferIndex - _bufferReleasedCount) % Constants.AudioDeviceBufferCountMax; uint bufferIndex = (_releasedBufferIndex - _bufferReleasedCount) % Constants.AudioDeviceBufferCountMax;
for (int i = 0; i < GetTotalBufferCount(); i++) uint totalBufferCount = GetTotalBufferCount();
for (int i = 0; i < totalBufferCount; i++)
{ {
if (_buffers[bufferIndex].BufferTag == bufferTag) if (_buffers[bufferIndex].BufferTag == bufferTag)
{ {

View file

@ -125,7 +125,7 @@ namespace Ryujinx.Ava.UI.Windows
public static Bgra32[] GetBuffer(Image<Bgra32> image) public static Bgra32[] GetBuffer(Image<Bgra32> image)
{ {
return image.TryGetSinglePixelSpan(out var data) ? data.ToArray() : new Bgra32[0]; return image.TryGetSinglePixelSpan(out var data) ? data.ToArray() : Array.Empty<Bgra32>();
} }
private static int GetColorScore(Dictionary<int, int> dominantColorBin, int maxHitCount, PaletteColor color) private static int GetColorScore(Dictionary<int, int> dominantColorBin, int maxHitCount, PaletteColor color)

View file

@ -17,7 +17,7 @@ namespace Ryujinx.Graphics.Vulkan.Queries
_counterQueues = new CounterQueue[count]; _counterQueues = new CounterQueue[count];
for (int index = 0; index < count; index++) for (int index = 0; index < _counterQueues.Length; index++)
{ {
CounterType type = (CounterType)index; CounterType type = (CounterType)index;
_counterQueues[index] = new CounterQueue(gd, device, pipeline, type); _counterQueues[index] = new CounterQueue(gd, device, pipeline, type);

View file

@ -29,7 +29,7 @@ namespace Ryujinx.Graphics.Vulkan
uint structSize = 0; uint structSize = 0;
for (int i = 0; i < count; ++i) for (int i = 0; i < Map.Length; ++i)
{ {
var typeSize = SizeOf(description[i].Type); var typeSize = SizeOf(description[i].Type);
Map[i] = new SpecializationMapEntry(description[i].Id, structSize, typeSize); Map[i] = new SpecializationMapEntry(description[i].Id, structSize, typeSize);
@ -46,11 +46,10 @@ namespace Ryujinx.Graphics.Vulkan
// For advanced mapping with overlapping or staggered fields // For advanced mapping with overlapping or staggered fields
public SpecDescription(SpecializationMapEntry[] map) public SpecDescription(SpecializationMapEntry[] map)
{ {
int count = map.Length;
Map = map; Map = map;
uint structSize = 0; uint structSize = 0;
for (int i = 0; i < count; ++i) for (int i = 0; i < map.Length; ++i)
{ {
structSize = Math.Max(structSize, map[i].Offset + (uint)map[i].Size); structSize = Math.Max(structSize, map[i].Offset + (uint)map[i].Size);
} }

View file

@ -60,10 +60,9 @@ namespace Ryujinx.Graphics.Vulkan
private void RecreateSwapchain() private void RecreateSwapchain()
{ {
var oldSwapchain = _swapchain; var oldSwapchain = _swapchain;
int imageCount = _swapchainImageViews.Length;
_vsyncModeChanged = false; _vsyncModeChanged = false;
for (int i = 0; i < imageCount; i++) for (int i = 0; i < _swapchainImageViews.Length; i++)
{ {
_swapchainImageViews[i].Dispose(); _swapchainImageViews[i].Dispose();
} }
@ -147,7 +146,7 @@ namespace Ryujinx.Graphics.Vulkan
_swapchainImageViews = new Auto<DisposableImageView>[imageCount]; _swapchainImageViews = new Auto<DisposableImageView>[imageCount];
for (int i = 0; i < imageCount; i++) for (int i = 0; i < _swapchainImageViews.Length; i++)
{ {
_swapchainImageViews[i] = CreateSwapchainImageView(_swapchainImages[i], surfaceFormat.Format); _swapchainImageViews[i] = CreateSwapchainImageView(_swapchainImages[i], surfaceFormat.Format);
} }

View file

@ -49,12 +49,12 @@ namespace Ryujinx.HLE.HOS.Ipc
public static IpcHandleDesc MakeCopy(params int[] handles) public static IpcHandleDesc MakeCopy(params int[] handles)
{ {
return new IpcHandleDesc(handles, new int[0]); return new IpcHandleDesc(handles, Array.Empty<int>());
} }
public static IpcHandleDesc MakeMove(params int[] handles) public static IpcHandleDesc MakeMove(params int[] handles)
{ {
return new IpcHandleDesc(new int[0], handles); return new IpcHandleDesc(Array.Empty<int>(), handles);
} }
public byte[] GetBytes() public byte[] GetBytes()

View file

@ -1,3 +1,4 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
@ -132,7 +133,7 @@ namespace Ryujinx.HLE.HOS.Ipc
word0 |= (ReceiveBuff.Count & 0xf) << 24; word0 |= (ReceiveBuff.Count & 0xf) << 24;
word0 |= (ExchangeBuff.Count & 0xf) << 28; word0 |= (ExchangeBuff.Count & 0xf) << 28;
byte[] handleData = new byte[0]; byte[] handleData = Array.Empty<byte>();
if (HandleDesc != null) if (HandleDesc != null)
{ {
@ -202,7 +203,7 @@ namespace Ryujinx.HLE.HOS.Ipc
word0 |= (ReceiveBuff.Count & 0xf) << 24; word0 |= (ReceiveBuff.Count & 0xf) << 24;
word0 |= (ExchangeBuff.Count & 0xf) << 28; word0 |= (ExchangeBuff.Count & 0xf) << 28;
byte[] handleData = new byte[0]; byte[] handleData = Array.Empty<byte>();
if (HandleDesc != null) if (HandleDesc != null)
{ {

View file

@ -1,7 +1,6 @@
using Ryujinx.Common; using Ryujinx.Common;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading; using System.Threading;
namespace Ryujinx.HLE.HOS.Kernel.Common namespace Ryujinx.HLE.HOS.Kernel.Common
@ -86,7 +85,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
{ {
Interlocked.Exchange(ref _enforceWakeupFromSpinWait, 0); Interlocked.Exchange(ref _enforceWakeupFromSpinWait, 0);
next = _waitingObjects.OrderBy(x => x.TimePoint).FirstOrDefault(); next = GetNextWaitingObject();
} }
if (next != null) 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) public static long ConvertNanosecondsToMilliseconds(long time)
{ {
time /= 1000000; time /= 1000000;

View file

@ -233,7 +233,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
// If the location name is too long, error out. // If the location name is too long, error out.
if (locationName.Length > 0x24) if (locationName.Length > 0x24)
{ {
outLocationNameArray = new string[0]; outLocationNameArray = Array.Empty<string>();
return ResultCode.LocationNameTooLong; return ResultCode.LocationNameTooLong;
} }

View file

@ -27,7 +27,9 @@ namespace Ryujinx.Input.SDL2
SDL2Driver.Instance.OnJoystickDisconnected += HandleJoyStickDisconnected; SDL2Driver.Instance.OnJoystickDisconnected += HandleJoyStickDisconnected;
// Add already connected gamepads // Add already connected gamepads
for (int joystickIndex = 0; joystickIndex < SDL_NumJoysticks(); joystickIndex++) int numJoysticks = SDL_NumJoysticks();
for (int joystickIndex = 0; joystickIndex < numJoysticks; joystickIndex++)
{ {
HandleJoyStickConnected(joystickIndex, SDL_JoystickGetDeviceInstanceID(joystickIndex)); HandleJoyStickConnected(joystickIndex, SDL_JoystickGetDeviceInstanceID(joystickIndex));
} }

View file

@ -78,7 +78,7 @@ namespace Ryujinx.Memory.Tests
IEnumerable<MemoryRange> IVirtualMemoryManager.GetPhysicalRegions(ulong va, ulong size) IEnumerable<MemoryRange> IVirtualMemoryManager.GetPhysicalRegions(ulong va, ulong size)
{ {
return NoMappings ? new MemoryRange[0] : new MemoryRange[] { new MemoryRange(va, size) }; return NoMappings ? Array.Empty<MemoryRange>() : new MemoryRange[] { new MemoryRange(va, size) };
} }
public bool IsMapped(ulong va) public bool IsMapped(ulong va)