forked from Mirror/Ryujinx
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:
parent
81691b9e37
commit
23c844b2aa
15 changed files with 48 additions and 31 deletions
|
@ -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);
|
||||||
|
|
|
@ -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];
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Reference in a new issue