From 2991f6205298741a9c17aa29b73a573b1e431ea8 Mon Sep 17 00:00:00 2001 From: Kurt Date: Mon, 28 Feb 2022 18:06:45 -0800 Subject: [PATCH] Reduce allocation for eggmove loading --- PKHeX.Core/Legality/Structures/EggMoves.cs | 93 ++++++++++++---------- 1 file changed, 49 insertions(+), 44 deletions(-) diff --git a/PKHeX.Core/Legality/Structures/EggMoves.cs b/PKHeX.Core/Legality/Structures/EggMoves.cs index 5b08a8f77..9d7a17715 100644 --- a/PKHeX.Core/Legality/Structures/EggMoves.cs +++ b/PKHeX.Core/Legality/Structures/EggMoves.cs @@ -24,16 +24,17 @@ namespace PKHeX.Core for (int i = 1; i < entries.Length; i++) { int start = ReadInt16LittleEndian(data[((i - 1) * 2)..]) - baseOffset; - int end = data[start..].IndexOf((byte)0xFF) + start; - if (start == end) + var slice = data[start..]; + int moveCount = slice.IndexOf((byte)0xFF); + if (moveCount == 0) { entries[i] = empty; continue; } - int[] moves = new int[end - start]; - for (int m = start; m < end; m++) - moves[m - start] = data[m]; + int[] moves = new int[moveCount]; + for (int m = 0; m < moves.Length; m++) + moves[m] = slice[m]; entries[i] = new EggMoves2(moves); } @@ -44,60 +45,64 @@ namespace PKHeX.Core public sealed class EggMoves6 : EggMoves { - private static readonly EggMoves6 None = new(Array.Empty()); - private EggMoves6(int[] moves) : base(moves) { } - private static EggMoves6 Get(ReadOnlySpan data) - { - if (data.Length == 0) - return None; - - int count = ReadInt16LittleEndian(data); - var moves = new int[count]; - var span = data[2..]; - for (int i = 0; i < moves.Length; i++) - moves[i] = ReadInt16LittleEndian(span[(i * 2)..]); - return new EggMoves6(moves); - } - public static EggMoves6[] GetArray(BinLinkerAccessor entries) { - EggMoves6[] data = new EggMoves6[entries.Length]; - for (int i = 0; i < data.Length; i++) - data[i] = Get(entries[i]); - return data; + var result = new EggMoves6[entries.Length]; + var empty = result[0] = new EggMoves6(Array.Empty()); + for (int i = 1; i < result.Length; i++) + { + var data = entries[i]; + int count = ReadInt16LittleEndian(data); + if (count == 0) + { + result[i] = empty; + continue; + } + + var moves = new int[count]; + var span = data[2..]; + for (int j = 0; j < moves.Length; j++) + moves[j] = ReadInt16LittleEndian(span[(j * 2)..]); + result[i] = new EggMoves6(moves); + } + return result; } } public sealed class EggMoves7 : EggMoves { - private static readonly EggMoves7 None = new(Array.Empty()); public readonly int FormTableIndex; private EggMoves7(int[] moves, int formIndex = 0) : base(moves) => FormTableIndex = formIndex; - private static EggMoves7 Get(ReadOnlySpan data) - { - if (data.Length == 0) - return None; - - int formIndex = ReadInt16LittleEndian(data); - int count = ReadInt16LittleEndian(data[2..]); - var moves = new int[count]; - - var moveSpan = data[4..]; - for (int i = 0; i < moves.Length; i++) - moves[i] = ReadInt16LittleEndian(moveSpan[(i * 2)..]); - return new EggMoves7(moves, formIndex); - } - public static EggMoves7[] GetArray(BinLinkerAccessor entries) { - EggMoves7[] data = new EggMoves7[entries.Length]; - for (int i = 0; i < data.Length; i++) - data[i] = Get(entries[i]); - return data; + var result = new EggMoves7[entries.Length]; + var empty = result[0] = new EggMoves7(Array.Empty()); + for (int i = 1; i < result.Length; i++) + { + var data = entries[i]; + int count = ReadInt16LittleEndian(data[2..]); + int formIndex = ReadInt16LittleEndian(data); + if (count == 0) + { + // Might need to keep track of the Form Index for unavailable forms pointing to valid forms. + if (formIndex != 0) + result[i] = new EggMoves7(Array.Empty(), formIndex); + else + result[i] = empty; + continue; + } + + var moves = new int[count]; + var span = data[4..]; + for (int j = 0; j < moves.Length; j++) + moves[j] = ReadInt16LittleEndian(span[(j * 2)..]); + result[i] = new EggMoves7(moves, formIndex); + } + return result; } } }