From c40c3905e2836e8b105406430c33659a84c2e3ca Mon Sep 17 00:00:00 2001
From: Berkan Diler <b.diler@gmx.de>
Date: Wed, 19 Oct 2022 01:31:34 +0200
Subject: [PATCH] Avoid allocations in .Parse methods (#3760)

* Avoid allocations in .Parse methods

Use the Span overloads of the Parse methods when possible to avoid string allocations and remove one unnecessarry array allocation

* Avoid another string allocation
---
 Ryujinx.Common/Utilities/EmbeddedResources.cs       |  2 +-
 Ryujinx.HLE/HOS/Diagnostics/Demangler/Demangler.cs  |  2 +-
 Ryujinx.HLE/HOS/Services/Nfc/Nfp/NfpManager/INfp.cs | 10 +++++-----
 Ryujinx.HLE/HOS/Tamper/InstructionHelper.cs         |  3 +--
 Ryujinx.HLE/Loaders/Mods/IPSwitchPatcher.cs         |  2 +-
 Ryujinx.HLE/Utilities/StringUtils.cs                |  2 +-
 6 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/Ryujinx.Common/Utilities/EmbeddedResources.cs b/Ryujinx.Common/Utilities/EmbeddedResources.cs
index 6113bc72..286d2c5c 100644
--- a/Ryujinx.Common/Utilities/EmbeddedResources.cs
+++ b/Ryujinx.Common/Utilities/EmbeddedResources.cs
@@ -129,7 +129,7 @@ namespace Ryujinx.Common
 
         private static (Assembly, string) ResolveManifestPath(string filename)
         {
-            var segments = filename.Split(new[] { '/' }, 2, StringSplitOptions.RemoveEmptyEntries);
+            var segments = filename.Split('/', 2, StringSplitOptions.RemoveEmptyEntries);
 
             if (segments.Length >= 2)
             {
diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Demangler.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Demangler.cs
index 1e621121..be5b7539 100644
--- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Demangler.cs
+++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Demangler.cs
@@ -918,7 +918,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler
                 return -1;
             }
 
-            return int.Parse(part.Substring(0, numberLength));
+            return int.Parse(part.AsSpan(0, numberLength));
         }
 
         private string ParseNumber(bool isSigned = false)
diff --git a/Ryujinx.HLE/HOS/Services/Nfc/Nfp/NfpManager/INfp.cs b/Ryujinx.HLE/HOS/Services/Nfc/Nfp/NfpManager/INfp.cs
index 9dfa677c..fc0c0647 100644
--- a/Ryujinx.HLE/HOS/Services/Nfc/Nfp/NfpManager/INfp.cs
+++ b/Ryujinx.HLE/HOS/Services/Nfc/Nfp/NfpManager/INfp.cs
@@ -816,11 +816,11 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp
                                 Reserved = new Array57<byte>()
                             };
 
-                            modelInfo.CharacterId      = BinaryPrimitives.ReverseEndianness(ushort.Parse(context.Device.System.NfpDevices[i].AmiiboId.Substring(0, 4), NumberStyles.HexNumber));
-                            modelInfo.CharacterVariant = byte.Parse(context.Device.System.NfpDevices[i].AmiiboId.Substring(4, 2), NumberStyles.HexNumber);
-                            modelInfo.Series           = byte.Parse(context.Device.System.NfpDevices[i].AmiiboId.Substring(12, 2), NumberStyles.HexNumber);
-                            modelInfo.ModelNumber      = ushort.Parse(context.Device.System.NfpDevices[i].AmiiboId.Substring(8, 4), NumberStyles.HexNumber);
-                            modelInfo.Type             = byte.Parse(context.Device.System.NfpDevices[i].AmiiboId.Substring(6, 2), NumberStyles.HexNumber);
+                            modelInfo.CharacterId      = BinaryPrimitives.ReverseEndianness(ushort.Parse(context.Device.System.NfpDevices[i].AmiiboId.AsSpan(0, 4), NumberStyles.HexNumber));
+                            modelInfo.CharacterVariant = byte.Parse(context.Device.System.NfpDevices[i].AmiiboId.AsSpan(4, 2), NumberStyles.HexNumber);
+                            modelInfo.Series           = byte.Parse(context.Device.System.NfpDevices[i].AmiiboId.AsSpan(12, 2), NumberStyles.HexNumber);
+                            modelInfo.ModelNumber      = ushort.Parse(context.Device.System.NfpDevices[i].AmiiboId.AsSpan(8, 4), NumberStyles.HexNumber);
+                            modelInfo.Type             = byte.Parse(context.Device.System.NfpDevices[i].AmiiboId.AsSpan(6, 2), NumberStyles.HexNumber);
 
                             context.Memory.Write(outputPosition, modelInfo);
 
diff --git a/Ryujinx.HLE/HOS/Tamper/InstructionHelper.cs b/Ryujinx.HLE/HOS/Tamper/InstructionHelper.cs
index d34f4cf8..e85d99c7 100644
--- a/Ryujinx.HLE/HOS/Tamper/InstructionHelper.cs
+++ b/Ryujinx.HLE/HOS/Tamper/InstructionHelper.cs
@@ -122,9 +122,8 @@ namespace Ryujinx.HLE.HOS.Tamper
                 for (int nybbleIndex = 0; nybbleIndex < wordSize; nybbleIndex++)
                 {
                     int index = wordIndex * wordSize + nybbleIndex;
-                    string byteData = word.Substring(nybbleIndex, 1);
 
-                    instruction[index] = byte.Parse(byteData, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
+                    instruction[index] = byte.Parse(word.AsSpan(nybbleIndex, 1), NumberStyles.HexNumber, CultureInfo.InvariantCulture);
                 }
             }
 
diff --git a/Ryujinx.HLE/Loaders/Mods/IPSwitchPatcher.cs b/Ryujinx.HLE/Loaders/Mods/IPSwitchPatcher.cs
index 8cc03d05..416fc1b4 100644
--- a/Ryujinx.HLE/Loaders/Mods/IPSwitchPatcher.cs
+++ b/Ryujinx.HLE/Loaders/Mods/IPSwitchPatcher.cs
@@ -132,7 +132,7 @@ namespace Ryujinx.HLE.Loaders.Mods
         {
             if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
             {
-                return int.TryParse(str.Substring(2), System.Globalization.NumberStyles.HexNumber, null, out value);
+                return int.TryParse(str.AsSpan(2), System.Globalization.NumberStyles.HexNumber, null, out value);
             }
             else
             {
diff --git a/Ryujinx.HLE/Utilities/StringUtils.cs b/Ryujinx.HLE/Utilities/StringUtils.cs
index 269f9b55..a64d451c 100644
--- a/Ryujinx.HLE/Utilities/StringUtils.cs
+++ b/Ryujinx.HLE/Utilities/StringUtils.cs
@@ -54,7 +54,7 @@ namespace Ryujinx.HLE.Utilities
 
             for (int index = 0; index < bytesInHex; index++)
             {
-                output[index] = byte.Parse(hexString.Substring(index * 2, 2), NumberStyles.HexNumber);
+                output[index] = byte.Parse(hexString.AsSpan(index * 2, 2), NumberStyles.HexNumber);
             }
 
             return output;