diff --git a/ARMeilleure/Decoders/OpCodeTable.cs b/ARMeilleure/Decoders/OpCodeTable.cs
index 3f24986c5..54abb1418 100644
--- a/ARMeilleure/Decoders/OpCodeTable.cs
+++ b/ARMeilleure/Decoders/OpCodeTable.cs
@@ -1339,7 +1339,7 @@ namespace ARMeilleure.Decoders
 
         private static void SetT32(string encoding, InstName name, InstEmitter emitter, MakeOp makeOp)
         {
-            string reversedEncoding = encoding.Substring(16) + encoding.Substring(0, 16);
+            string reversedEncoding = $"{encoding.AsSpan(16)}{encoding.AsSpan(0, 16)}";
             MakeOp reversedMakeOp =
                 (inst, address, opCode)
                     => makeOp(inst, address, (int)BitOperations.RotateRight((uint)opCode, 16));
@@ -1353,7 +1353,7 @@ namespace ARMeilleure.Decoders
             string thumbEncoding = encoding;
             if (thumbEncoding.StartsWith("<<<<"))
             {
-                thumbEncoding = "1110" + thumbEncoding.Substring(4);
+                thumbEncoding = $"1110{thumbEncoding.AsSpan(4)}";
             }
             SetT32(thumbEncoding, name, emitter, makeOpT32);
         }
@@ -1365,19 +1365,19 @@ namespace ARMeilleure.Decoders
             string thumbEncoding = encoding;
             if (thumbEncoding.StartsWith("11110100"))
             {
-                thumbEncoding = "11111001" + encoding.Substring(8);
+                thumbEncoding = $"11111001{encoding.AsSpan(8)}";
             }
             else if (thumbEncoding.StartsWith("1111001x"))
             {
-                thumbEncoding = "111x1111" + encoding.Substring(8);
+                thumbEncoding = $"111x1111{encoding.AsSpan(8)}";
             }
             else if (thumbEncoding.StartsWith("11110010"))
             {
-                thumbEncoding = "11101111" + encoding.Substring(8);
+                thumbEncoding = $"11101111{encoding.AsSpan(8)}";
             }
             else if (thumbEncoding.StartsWith("11110011"))
             {
-                thumbEncoding = "11111111" + encoding.Substring(8);
+                thumbEncoding = $"11111111{encoding.AsSpan(8)}";
             }
             else
             {
diff --git a/ARMeilleure/Translation/PTC/Ptc.cs b/ARMeilleure/Translation/PTC/Ptc.cs
index e5b4623d2..e5e0b2a54 100644
--- a/ARMeilleure/Translation/PTC/Ptc.cs
+++ b/ARMeilleure/Translation/PTC/Ptc.cs
@@ -183,8 +183,8 @@ namespace ARMeilleure.Translation.PTC
 
         private void PreLoad()
         {
-            string fileNameActual = string.Concat(CachePathActual, ".cache");
-            string fileNameBackup = string.Concat(CachePathBackup, ".cache");
+            string fileNameActual = $"{CachePathActual}.cache";
+            string fileNameBackup = $"{CachePathBackup}.cache";
 
             FileInfo fileInfoActual = new FileInfo(fileNameActual);
             FileInfo fileInfoBackup = new FileInfo(fileNameBackup);
@@ -400,8 +400,8 @@ namespace ARMeilleure.Translation.PTC
 
             try
             {
-                string fileNameActual = string.Concat(CachePathActual, ".cache");
-                string fileNameBackup = string.Concat(CachePathBackup, ".cache");
+                string fileNameActual = $"{CachePathActual}.cache";
+                string fileNameBackup = $"{CachePathBackup}.cache";
 
                 FileInfo fileInfoActual = new FileInfo(fileNameActual);
 
diff --git a/ARMeilleure/Translation/PTC/PtcProfiler.cs b/ARMeilleure/Translation/PTC/PtcProfiler.cs
index 0d5546283..030ccff5f 100644
--- a/ARMeilleure/Translation/PTC/PtcProfiler.cs
+++ b/ARMeilleure/Translation/PTC/PtcProfiler.cs
@@ -125,8 +125,8 @@ namespace ARMeilleure.Translation.PTC
         {
             _lastHash = default;
 
-            string fileNameActual = string.Concat(_ptc.CachePathActual, ".info");
-            string fileNameBackup = string.Concat(_ptc.CachePathBackup, ".info");
+            string fileNameActual = $"{_ptc.CachePathActual}.info";
+            string fileNameBackup = $"{_ptc.CachePathBackup}.info";
 
             FileInfo fileInfoActual = new FileInfo(fileNameActual);
             FileInfo fileInfoBackup = new FileInfo(fileNameBackup);
@@ -246,8 +246,8 @@ namespace ARMeilleure.Translation.PTC
         {
             _waitEvent.Reset();
 
-            string fileNameActual = string.Concat(_ptc.CachePathActual, ".info");
-            string fileNameBackup = string.Concat(_ptc.CachePathBackup, ".info");
+            string fileNameActual = $"{_ptc.CachePathActual}.info";
+            string fileNameBackup = $"{_ptc.CachePathBackup}.info";
 
             FileInfo fileInfoActual = new FileInfo(fileNameActual);
 
diff --git a/Ryujinx.Ava/UI/ViewModels/ControllerSettingsViewModel.cs b/Ryujinx.Ava/UI/ViewModels/ControllerSettingsViewModel.cs
index 82a75788d..5d5ca5f83 100644
--- a/Ryujinx.Ava/UI/ViewModels/ControllerSettingsViewModel.cs
+++ b/Ryujinx.Ava/UI/ViewModels/ControllerSettingsViewModel.cs
@@ -435,7 +435,7 @@ namespace Ryujinx.Ava.UI.ViewModels
 
             if (str.Length > MaxSize)
             {
-                return str.Substring(0, MaxSize - Ellipsis.Length) + Ellipsis;
+                return $"{str.AsSpan(0, MaxSize - Ellipsis.Length)}{Ellipsis}";
             }
 
             return str;
diff --git a/Ryujinx.Common/Utilities/UInt128Utils.cs b/Ryujinx.Common/Utilities/UInt128Utils.cs
index 8cc437d17..af8521b4e 100644
--- a/Ryujinx.Common/Utilities/UInt128Utils.cs
+++ b/Ryujinx.Common/Utilities/UInt128Utils.cs
@@ -1,4 +1,5 @@
 using System;
+using System.Globalization;
 
 namespace Ryujinx.Common.Utilities
 {
@@ -6,7 +7,7 @@ namespace Ryujinx.Common.Utilities
     {
         public static UInt128 FromHex(string hex)
         {
-            return new UInt128((ulong)Convert.ToInt64(hex.Substring(0, 16), 16), (ulong)Convert.ToInt64(hex.Substring(16), 16));
+            return new UInt128(ulong.Parse(hex.AsSpan(0, 16), NumberStyles.HexNumber), ulong.Parse(hex.AsSpan(16), NumberStyles.HexNumber));
         }
 
         public static UInt128 CreateRandom()
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs
index 3dbd73b27..263eada6f 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs
@@ -2,6 +2,7 @@ using Ryujinx.Graphics.Shader.IntermediateRepresentation;
 using Ryujinx.Graphics.Shader.StructuredIr;
 using Ryujinx.Graphics.Shader.Translation;
 using System;
+using System.Text;
 
 using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenHelper;
 using static Ryujinx.Graphics.Shader.StructuredIr.InstructionInfo;
@@ -44,11 +45,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
             bool isArray   = (texOp.Type & SamplerType.Array)   != 0;
             bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
 
-            string texCall;
+            var texCallBuilder = new StringBuilder();
 
             if (texOp.Inst == Instruction.ImageAtomic)
             {
-                texCall = (texOp.Flags & TextureFlags.AtomicMask) switch {
+                texCallBuilder.Append((texOp.Flags & TextureFlags.AtomicMask) switch {
                     TextureFlags.Add        => "imageAtomicAdd",
                     TextureFlags.Minimum    => "imageAtomicMin",
                     TextureFlags.Maximum    => "imageAtomicMax",
@@ -60,11 +61,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
                     TextureFlags.Swap       => "imageAtomicExchange",
                     TextureFlags.CAS        => "imageAtomicCompSwap",
                     _                       => "imageAtomicAdd",
-                };
+                });
             }
             else
             {
-                texCall = texOp.Inst == Instruction.ImageLoad ? "imageLoad" : "imageStore";
+                texCallBuilder.Append(texOp.Inst == Instruction.ImageLoad ? "imageLoad" : "imageStore");
             }
 
             int srcIndex = isBindless ? 1 : 0;
@@ -83,7 +84,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
 
             string imageName = OperandManager.GetImageName(context.Config.Stage, texOp, indexExpr);
 
-            texCall += "(" + imageName;
+            texCallBuilder.Append('(');
+            texCallBuilder.Append(imageName);
 
             int coordsCount = texOp.Type.GetDimensions();
 
@@ -91,7 +93,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
 
             void Append(string str)
             {
-                texCall += ", " + str;
+                texCallBuilder.Append(", ");
+                texCallBuilder.Append(str);
             }
 
             string ApplyScaling(string vector)
@@ -107,11 +110,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
                     if (pCount == 3 && isArray)
                     {
                         // The array index is not scaled, just x and y.
-                        vector = "ivec3(Helper_TexelFetchScale((" + vector + ").xy, " + scaleIndex + "), (" + vector + ").z)";
+                        vector = $"ivec3(Helper_TexelFetchScale(({vector}).xy, {scaleIndex}), ({vector}).z)";
                     }
                     else if (pCount == 2 && !isArray)
                     {
-                        vector = "Helper_TexelFetchScale(" + vector + ", " + scaleIndex + ")";
+                        vector = $"Helper_TexelFetchScale({vector}, {scaleIndex})";
                     }
                 }
 
@@ -127,7 +130,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
                     elems[index] = Src(AggregateType.S32);
                 }
 
-                Append(ApplyScaling("ivec" + pCount + "(" + string.Join(", ", elems) + ")"));
+                Append(ApplyScaling($"ivec{pCount}({string.Join(", ", elems)})"));
             }
             else
             {
@@ -164,7 +167,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
                     _                => string.Empty
                 };
 
-                Append(prefix + "vec4(" + string.Join(", ", cElems) + ")");
+                Append($"{prefix}vec4({string.Join(", ", cElems)})");
             }
 
             if (texOp.Inst == Instruction.ImageAtomic)
@@ -185,19 +188,26 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
 
                 Append(value);
 
-                texCall += ")";
+                texCallBuilder.Append(')');
 
                 if (type != AggregateType.S32)
                 {
-                    texCall = "int(" + texCall + ")";
+                    texCallBuilder
+                        .Insert(0, "int(")
+                        .Append(')');
                 }
             }
             else
             {
-                texCall += ")" + (texOp.Inst == Instruction.ImageLoad ? GetMaskMultiDest(texOp.Index) : "");
+                texCallBuilder.Append(')');
+
+                if (texOp.Inst == Instruction.ImageLoad)
+                {
+                    texCallBuilder.Append(GetMaskMultiDest(texOp.Index));
+                }
             }
 
-            return texCall;
+            return texCallBuilder.ToString();
         }
 
         public static string LoadAttribute(CodeGenContext context, AstOperation operation)
@@ -827,7 +837,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
 
         private static string GetMask(int index)
         {
-            return '.' + "rgba".Substring(index, 1);
+            return $".{"rgba".AsSpan(index, 1)}";
         }
 
         private static string GetMaskMultiDest(int mask)
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenPacking.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenPacking.cs
index ecb90c1e0..5a888e9c5 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenPacking.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenPacking.cs
@@ -1,4 +1,5 @@
 using Ryujinx.Graphics.Shader.StructuredIr;
+using System;
 
 using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenHelper;
 using static Ryujinx.Graphics.Shader.StructuredIr.InstructionInfo;
@@ -49,7 +50,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
 
         private static string GetMask(int index)
         {
-            return '.' + "xy".Substring(index, 1);
+            return $".{"xy".AsSpan(index, 1)}";
         }
     }
 }
\ No newline at end of file
diff --git a/Ryujinx.Graphics.Shader/Decoders/InstTable.cs b/Ryujinx.Graphics.Shader/Decoders/InstTable.cs
index 911f15816..eaa77930b 100644
--- a/Ryujinx.Graphics.Shader/Decoders/InstTable.cs
+++ b/Ryujinx.Graphics.Shader/Decoders/InstTable.cs
@@ -1,4 +1,5 @@
 using Ryujinx.Graphics.Shader.Instructions;
+using System;
 
 namespace Ryujinx.Graphics.Shader.Decoders
 {
@@ -329,18 +330,18 @@ namespace Ryujinx.Graphics.Shader.Decoders
 
         private static void Add(string encoding, InstName name, InstEmitter emitter, InstProps props = InstProps.None)
         {
-            encoding = encoding.Substring(0, EncodingBits);
+            ReadOnlySpan<char> encodingPart = encoding.AsSpan(0, EncodingBits);
 
-            int bit = encoding.Length - 1;
+            int bit = encodingPart.Length - 1;
             int value = 0;
             int xMask = 0;
             int xBits = 0;
 
-            int[] xPos = new int[encoding.Length];
+            int[] xPos = new int[encodingPart.Length];
 
-            for (int index = 0; index < encoding.Length; index++, bit--)
+            for (int index = 0; index < encodingPart.Length; index++, bit--)
             {
-                char chr = encoding[index];
+                char chr = encodingPart[index];
 
                 if (chr == '1')
                 {
diff --git a/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs b/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs
index 95a2fcdac..0b91d3a2d 100644
--- a/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs
+++ b/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs
@@ -141,8 +141,8 @@ namespace Ryujinx.HLE.FileSystem
                     return $"{rawPath}:/";
                 }
 
-                string basePath = rawPath.Substring(0, firstSeparatorOffset);
-                string fileName = rawPath.Substring(firstSeparatorOffset + 1);
+                var basePath = rawPath.AsSpan(0, firstSeparatorOffset);
+                var fileName = rawPath.AsSpan(firstSeparatorOffset + 1);
 
                 return $"{basePath}:/{fileName}";
             }
diff --git a/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/InlineResponses.cs b/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/InlineResponses.cs
index d48227a0f..c3e45d469 100644
--- a/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/InlineResponses.cs
+++ b/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/InlineResponses.cs
@@ -24,7 +24,7 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
             for (int maxStr = text.Length; maxStr >= 0; maxStr--)
             {
                 // This loop will probably will run only once.
-                bytes = encoding.GetBytes(text.Substring(0, maxStr));
+                bytes = encoding.GetBytes(text, 0, maxStr);
                 if (bytes.Length <= maxSize)
                 {
                     break;
diff --git a/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardRendererBase.cs b/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardRendererBase.cs
index 8216a65ee..71835e2da 100644
--- a/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardRendererBase.cs
+++ b/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardRendererBase.cs
@@ -292,20 +292,35 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
 
             _logoPosition = new Point(logoPositionX, logoPositionY);
         }
-
-        private RectangleF MeasureString(string text, Font font)
+        private static RectangleF MeasureString(string text, Font font)
         {
             RendererOptions options = new RendererOptions(font);
-            FontRectangle rectangle = TextMeasurer.Measure(text == "" ? " " : text, options);
 
             if (text == "")
             {
-                return new RectangleF(0, rectangle.Y, 0, rectangle.Height);
+                FontRectangle emptyRectangle = TextMeasurer.Measure(" ", options);
+
+                return new RectangleF(0, emptyRectangle.Y, 0, emptyRectangle.Height);
             }
-            else
+
+            FontRectangle rectangle = TextMeasurer.Measure(text, options);
+
+            return new RectangleF(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
+        }
+
+        private static RectangleF MeasureString(ReadOnlySpan<char> text, Font font)
+        {
+            RendererOptions options = new RendererOptions(font);
+            
+            if (text == "")
             {
-                return new RectangleF(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
+                FontRectangle emptyRectangle = TextMeasurer.Measure(" ", options);
+                return new RectangleF(0, emptyRectangle.Y, 0, emptyRectangle.Height);
             }
+
+            FontRectangle rectangle = TextMeasurer.Measure(text, options);
+
+            return new RectangleF(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
         }
 
         private void DrawTextBox(IImageProcessingContext context, SoftwareKeyboardUiState state)
@@ -354,8 +369,8 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
                 cursorBrush     = _selectionBoxBrush;
                 cursorPen       = _selectionBoxPen;
 
-                string textUntilBegin = state.InputText.Substring(0, state.CursorBegin);
-                string textUntilEnd   = state.InputText.Substring(0, state.CursorEnd);
+                ReadOnlySpan<char> textUntilBegin = state.InputText.AsSpan(0, state.CursorBegin);
+                ReadOnlySpan<char> textUntilEnd   = state.InputText.AsSpan(0, state.CursorEnd);
 
                 var selectionBeginRectangle = MeasureString(textUntilBegin, _inputTextFont);
                 var selectionEndRectangle   = MeasureString(textUntilEnd  , _inputTextFont);
@@ -374,9 +389,9 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
                 {
                     // Show the blinking cursor.
 
-                    int    cursorBegin         = Math.Min(state.InputText.Length, state.CursorBegin);
-                    string textUntilCursor     = state.InputText.Substring(0, cursorBegin);
-                    var    cursorTextRectangle = MeasureString(textUntilCursor, _inputTextFont);
+                    int                cursorBegin         = Math.Min(state.InputText.Length, state.CursorBegin);
+                    ReadOnlySpan<char> textUntilCursor     = state.InputText.AsSpan(0, cursorBegin);
+                    var                cursorTextRectangle = MeasureString(textUntilCursor, _inputTextFont);
 
                     cursorVisible       = true;
                     cursorPositionXLeft = inputTextX + cursorTextRectangle.Width + cursorTextRectangle.X;
@@ -387,7 +402,7 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
 
                         if (state.CursorBegin < state.InputText.Length)
                         {
-                            textUntilCursor      = state.InputText.Substring(0, cursorBegin + 1);
+                            textUntilCursor      = state.InputText.AsSpan(0, cursorBegin + 1);
                             cursorTextRectangle  = MeasureString(textUntilCursor, _inputTextFont);
                             cursorPositionXRight = inputTextX + cursorTextRectangle.Width + cursorTextRectangle.X;
                         }
diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/IntegerLiteral.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/IntegerLiteral.cs
index 951faa554..ea048d768 100644
--- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/IntegerLiteral.cs
+++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/IntegerLiteral.cs
@@ -1,4 +1,5 @@
 using System.IO;
+using System;
 
 namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
 {
@@ -25,7 +26,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
             if (_literalValue[0] == 'n')
             {
                 writer.Write("-");
-                writer.Write(_literalValue.Substring(1));
+                writer.Write(_literalValue.AsSpan(1));
             }
             else
             {
diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Demangler.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Demangler.cs
index be5b75392..a6618eca4 100644
--- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Demangler.cs
+++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Demangler.cs
@@ -32,9 +32,9 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler
 
         private bool ConsumeIf(string toConsume)
         {
-            string mangledPart = Mangled.Substring(_position);
+            var mangledPart = Mangled.AsSpan(_position);
 
-            if (mangledPart.StartsWith(toConsume))
+            if (mangledPart.StartsWith(toConsume.AsSpan()))
             {
                 _position += toConsume.Length;
 
@@ -44,14 +44,14 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler
             return false;
         }
 
-        private string PeekString(int offset = 0, int length = 1)
+        private ReadOnlySpan<char> PeekString(int offset = 0, int length = 1)
         {
             if (_position + offset >= length)
             {
                 return null;
             }
 
-            return Mangled.Substring(_position + offset, length);
+            return Mangled.AsSpan(_position + offset, length);
         }
 
         private char Peek(int offset = 0)
@@ -101,8 +101,8 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler
 
         private int ParseSeqId()
         {
-            string part     = Mangled.Substring(_position);
-            int    seqIdLen = 0;
+            ReadOnlySpan<char> part     = Mangled.AsSpan(_position);
+            int                seqIdLen = 0;
 
             for (; seqIdLen < part.Length; seqIdLen++)
             {
@@ -114,7 +114,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler
 
             _position += seqIdLen;
 
-            return FromBase36(part.Substring(0, seqIdLen));
+            return FromBase36(new string(part[..seqIdLen]));
         }
 
         //   <substitution> ::= S <seq-id> _
@@ -900,8 +900,8 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler
 
         private int ParsePositiveNumber()
         {
-            string part         = Mangled.Substring(_position);
-            int    numberLength = 0;
+            ReadOnlySpan<char> part         = Mangled.AsSpan(_position);
+            int                numberLength = 0;
 
             for (; numberLength < part.Length; numberLength++)
             {
@@ -918,7 +918,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler
                 return -1;
             }
 
-            return int.Parse(part.AsSpan(0, numberLength));
+            return int.Parse(part[..numberLength]);
         }
 
         private string ParseNumber(bool isSigned = false)
@@ -933,8 +933,8 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler
                 return null;
             }
 
-            string part         = Mangled.Substring(_position);
-            int    numberLength = 0;
+            ReadOnlySpan<char> part         = Mangled.AsSpan(_position);
+            int                numberLength = 0;
 
             for (; numberLength < part.Length; numberLength++)
             {
@@ -946,7 +946,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler
 
             _position += numberLength;
 
-            return part.Substring(0, numberLength);
+            return new string(part[..numberLength]);
         }
 
         // <source-name> ::= <positive length number> <identifier>
diff --git a/Ryujinx.HLE/HOS/Services/Account/Acc/Types/UserId.cs b/Ryujinx.HLE/HOS/Services/Account/Acc/Types/UserId.cs
index 1793067d0..e5577a94b 100644
--- a/Ryujinx.HLE/HOS/Services/Account/Acc/Types/UserId.cs
+++ b/Ryujinx.HLE/HOS/Services/Account/Acc/Types/UserId.cs
@@ -1,5 +1,6 @@
 using LibHac.Account;
 using System;
+using System.Globalization;
 using System.IO;
 using System.Linq;
 using System.Runtime.InteropServices;
@@ -35,8 +36,8 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
                 throw new ArgumentException("Invalid Hex value!", nameof(hex));
             }
 
-            Low  = Convert.ToInt64(hex.Substring(16), 16);
-            High = Convert.ToInt64(hex.Substring(0, 16), 16);
+            Low  = long.Parse(hex.AsSpan(16), NumberStyles.HexNumber);
+            High = long.Parse(hex.AsSpan(0, 16), NumberStyles.HexNumber);
         }
 
         public void Write(BinaryWriter binaryWriter)
diff --git a/Ryujinx.HLE/HOS/Services/Sockets/Nsd/IManager.cs b/Ryujinx.HLE/HOS/Services/Sockets/Nsd/IManager.cs
index 14bdd476c..b098e2edc 100644
--- a/Ryujinx.HLE/HOS/Services/Sockets/Nsd/IManager.cs
+++ b/Ryujinx.HLE/HOS/Services/Sockets/Nsd/IManager.cs
@@ -4,6 +4,7 @@ using Ryujinx.HLE.Exceptions;
 using Ryujinx.HLE.HOS.Services.Settings;
 using Ryujinx.HLE.HOS.Services.Sockets.Nsd.Manager;
 using Ryujinx.HLE.HOS.Services.Sockets.Nsd.Types;
+using System;
 using System.Text;
 
 namespace Ryujinx.HLE.HOS.Services.Sockets.Nsd
@@ -370,7 +371,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Nsd
                 return result;
             }
 
-            byte environmentType = identifier.Substring(0, 2) switch
+            byte environmentType = identifier.AsSpan(0, 2) switch
             {
                 "lp" => (byte)ApplicationServerEnvironmentType.Lp,
                 "sd" => (byte)ApplicationServerEnvironmentType.Sd,
diff --git a/Ryujinx.Horizon.Generators/CodeGenerator.cs b/Ryujinx.Horizon.Generators/CodeGenerator.cs
index 3a479eb74..29e1c75c8 100644
--- a/Ryujinx.Horizon.Generators/CodeGenerator.cs
+++ b/Ryujinx.Horizon.Generators/CodeGenerator.cs
@@ -4,9 +4,10 @@ namespace Ryujinx.Horizon.Generators
 {
     class CodeGenerator
     {
-        private const string Indent = "    ";
+        private const int IndentLength = 4;
+
         private readonly StringBuilder _sb;
-        private string _currentIndent;
+        private int _currentIndentCount;
 
         public CodeGenerator()
         {
@@ -32,12 +33,15 @@ namespace Ryujinx.Horizon.Generators
 
         public void IncreaseIndentation()
         {
-            _currentIndent += Indent;
+            _currentIndentCount++;
         }
 
         public void DecreaseIndentation()
         {
-            _currentIndent = _currentIndent.Substring(0, _currentIndent.Length - Indent.Length);
+            if (_currentIndentCount - 1 >= 0)
+            {
+                _currentIndentCount--;   
+            }
         }
 
         public void AppendLine()
@@ -47,7 +51,8 @@ namespace Ryujinx.Horizon.Generators
 
         public void AppendLine(string text)
         {
-            _sb.AppendLine(_currentIndent + text);
+            _sb.Append(' ', IndentLength * _currentIndentCount);
+            _sb.AppendLine(text);
         }
 
         public override string ToString()
diff --git a/Ryujinx.Horizon.Kernel.Generators/Kernel/SyscallGenerator.cs b/Ryujinx.Horizon.Kernel.Generators/Kernel/SyscallGenerator.cs
index f2a877030..8bc0800c1 100644
--- a/Ryujinx.Horizon.Kernel.Generators/Kernel/SyscallGenerator.cs
+++ b/Ryujinx.Horizon.Kernel.Generators/Kernel/SyscallGenerator.cs
@@ -417,7 +417,7 @@ namespace Ryujinx.Horizon.Generators.Kernel
 
         private static string GetPrefixedArgName(string name)
         {
-            return ArgVariablePrefix + name[0].ToString().ToUpperInvariant() + name.Substring(1);
+            return ArgVariablePrefix + char.ToUpperInvariant(name[0]) + name.Substring(1);
         }
 
         private static string GetCanonicalTypeName(Compilation compilation, SyntaxNode syntaxNode)
diff --git a/Ryujinx/Ui/Windows/AmiiboWindow.cs b/Ryujinx/Ui/Windows/AmiiboWindow.cs
index a8b021238..9140a14e9 100644
--- a/Ryujinx/Ui/Windows/AmiiboWindow.cs
+++ b/Ryujinx/Ui/Windows/AmiiboWindow.cs
@@ -344,7 +344,7 @@ namespace Ryujinx.Ui.Windows
 
             string imageUrl = _amiiboList.FirstOrDefault(amiibo => amiibo.Head + amiibo.Tail == _amiiboCharsComboBox.ActiveId).Image;
 
-            string usageString = "";
+            var usageStringBuilder = new StringBuilder();
 
             for (int i = 0; i < _amiiboList.Count; i++)
             {
@@ -358,19 +358,20 @@ namespace Ryujinx.Ui.Windows
                         {
                             foreach (AmiiboApiUsage usageItem in item.AmiiboUsage)
                             {
-                                usageString += Environment.NewLine + $"- {usageItem.Usage.Replace("/", Environment.NewLine + "-")}";
+                                usageStringBuilder.Append(Environment.NewLine);
+                                usageStringBuilder.Append($"- {usageItem.Usage.Replace("/", Environment.NewLine + "-")}");
 
                                 writable = usageItem.Write;
                             }
                         }
                     }
 
-                    if (usageString.Length == 0)
+                    if (usageStringBuilder.Length == 0)
                     {
-                        usageString = "Unknown.";
+                        usageStringBuilder.Append("Unknown.");
                     }
 
-                    _gameUsageLabel.Text = $"Usage{(writable ? " (Writable)" : "")} : {usageString}";
+                    _gameUsageLabel.Text = $"Usage{(writable ? " (Writable)" : "")} : {usageStringBuilder}";
                 }
             }
 
diff --git a/Ryujinx/Ui/Windows/ControllerWindow.cs b/Ryujinx/Ui/Windows/ControllerWindow.cs
index 002f8fe22..8c3a43c85 100644
--- a/Ryujinx/Ui/Windows/ControllerWindow.cs
+++ b/Ryujinx/Ui/Windows/ControllerWindow.cs
@@ -246,7 +246,7 @@ namespace Ryujinx.Ui.Windows
 
             if (str.Length > MaxSize)
             {
-                return str.Substring(0, MaxSize - ShrinkChars.Length) + ShrinkChars;
+                return $"{str.AsSpan(0, MaxSize - ShrinkChars.Length)}{ShrinkChars}";
             }
 
             return str;