Optimize string memory usage. Use Spans and StringBuilders where possible (#3933)
* Optimize string memory usage. Use ReadOnlySpan<char> and StringBuilder where possible. * Fix copypaste error * Code generator review fixes * Use if statement instead of switch * Code style fixes Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> * Another code style fix * Styling fix Co-authored-by: Mary-nyan <thog@protonmail.com> * Styling fix Co-authored-by: gdkchan <gab.dark.100@gmail.com> Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> Co-authored-by: Mary-nyan <thog@protonmail.com> Co-authored-by: gdkchan <gab.dark.100@gmail.com>
This commit is contained in:
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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>
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
Reference in New Issue
Block a user