From 4c69ce4e27224c6ddf6766b98a25acf38d6e1bb2 Mon Sep 17 00:00:00 2001 From: YoshiRulz Date: Thu, 24 Oct 2024 06:20:22 +1000 Subject: [PATCH] Avoid `string.Split` in `Database.InitializeWork` On my machine (Mono) in Release config, this reduces the number of string- and char-arrays allocated by an order of magnitude, bringing the gamedb's total bytes allocated down by -10%. --- .../Database/Database.cs | 34 ++++++++++++------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/BizHawk.Emulation.Common/Database/Database.cs b/src/BizHawk.Emulation.Common/Database/Database.cs index 11e6f686a1..0a85531db1 100644 --- a/src/BizHawk.Emulation.Common/Database/Database.cs +++ b/src/BizHawk.Emulation.Common/Database/Database.cs @@ -97,10 +97,18 @@ public static void SaveDatabaseEntry(CompactGameInfo gameInfo, string filename = public static CompactGameInfo ParseCGIRecord(string line) { const char FIELD_SEPARATOR = '\t'; - var items = line.Split(FIELD_SEPARATOR); - var field = 0; - var hashDigest = FormatHash(items[field++]); - var dumpStatus = items[field++].Trim() switch + var iFieldStart = -1; + var iFieldEnd = -1; // offset of the tab char, or line.Length if at end + string AdvanceAndReadField(out bool isLastField) + { + iFieldStart = iFieldEnd + 1; + iFieldEnd = line.IndexOf(FIELD_SEPARATOR, iFieldStart); + isLastField = iFieldEnd < 0; + if (isLastField) iFieldEnd = line.Length; + return line.Substring(startIndex: iFieldStart, length: iFieldEnd - iFieldStart); + } + var hashDigest = FormatHash(AdvanceAndReadField(out _)); + var dumpStatus = AdvanceAndReadField(out _).Trim() switch { "B" => RomStatus.BadDump, // see /Assets/gamedb/gamedb.txt "V" => RomStatus.BadDump, // see /Assets/gamedb/gamedb.txt @@ -112,21 +120,21 @@ public static CompactGameInfo ParseCGIRecord(string line) "U" => RomStatus.Unknown, _ => RomStatus.GoodDump }; - var knownName = items[field++]; - var sysID = items[field++]; + var knownName = AdvanceAndReadField(out _); + var sysID = AdvanceAndReadField(out var isLastField); string/*?*/ metadata = null; string region = string.Empty; string forcedCore = string.Empty; - if (field < items.Length) + if (!isLastField) { - _ = items[field++]; // rarely populated; possibly genre or just a remark - if (field < items.Length) + _ = AdvanceAndReadField(out isLastField); // rarely present; possibly genre or just a remark + if (!isLastField) { - metadata = items[field++]; - if (field < items.Length) + metadata = AdvanceAndReadField(out isLastField); + if (!isLastField) { - region = items[field++]; - if (field < items.Length) forcedCore = items[field++]; + region = AdvanceAndReadField(out isLastField); + if (!isLastField) forcedCore = AdvanceAndReadField(out isLastField); } } }