Span-ify BreedInfo, saves 10bytes heap alloc

the Actual result still needs to leave the stack, so that has to be heap allocated.
This commit is contained in:
Kurt 2022-03-06 13:04:56 -08:00
parent 9049ef99fd
commit 8f9de86347
8 changed files with 52 additions and 42 deletions

View file

@ -655,7 +655,7 @@ namespace PKHeX.Core
private static bool IsCheckInvalid(CheckResult? chk) => !(chk?.Valid ?? false);
private static bool IsCheckValid(CheckResult? chk) => chk?.Valid ?? false;
private static void FlagIncompatibleTransferHMs45(CheckMoveResult[] res, IReadOnlyList<int> currentMoves, int gen, IReadOnlyList<bool> HMLearned, bool KnowDefogWhirlpool)
private static void FlagIncompatibleTransferHMs45(CheckMoveResult[] res, IReadOnlyList<int> currentMoves, int gen, ReadOnlySpan<bool> HMLearned, bool KnowDefogWhirlpool)
{
// After all the moves from the generations 3 and 4,
// including egg moves if is the origin generation because some hidden moves are also special egg moves in gen 3
@ -675,7 +675,7 @@ namespace PKHeX.Core
}
// Flag moves that are only legal when learned from a past-gen HM source
for (int i = 0; i < HMLearned.Count; i++)
for (int i = 0; i < HMLearned.Length; i++)
{
if (HMLearned[i] && IsCheckValid(res[i]))
res[i] = new CheckMoveResult(res[i], Invalid, string.Format(LTransferMoveHM, gen, gen + 1), CurrentMove);
@ -689,7 +689,7 @@ namespace PKHeX.Core
return result;
}
private static void VerifyNoEmptyDuplicates(IReadOnlyList<int> moves, CheckMoveResult[] res)
private static void VerifyNoEmptyDuplicates(ReadOnlySpan<int> moves, CheckMoveResult[] res)
{
bool emptySlot = false;
for (int i = 0; i < 4; i++)
@ -714,7 +714,7 @@ namespace PKHeX.Core
}
}
private static void FlagDuplicateMovesAfterIndex(IReadOnlyList<int> moves, CheckMoveResult[] res, int index, int move)
private static void FlagDuplicateMovesAfterIndex(ReadOnlySpan<int> moves, CheckMoveResult[] res, int index, int move)
{
for (int i = index + 1; i < 4; i++)
{
@ -725,7 +725,7 @@ namespace PKHeX.Core
}
}
private static void FlagEmptySlotsBeforeIndex(IReadOnlyList<int> moves, CheckMoveResult[] res, int index)
private static void FlagEmptySlotsBeforeIndex(ReadOnlySpan<int> moves, CheckMoveResult[] res, int index)
{
for (int i = index - 1; i >= 0; i--)
{

View file

@ -12,21 +12,21 @@ namespace PKHeX.Core
public readonly T[] Actual;
/// <summary> Indicates all possible sources of each move. </summary>
public readonly byte[] Possible;
public readonly Span<byte> Possible;
/// <summary> Level Up entry for the egg. </summary>
public readonly Learnset Learnset;
/// <summary> Moves the egg knows after it is finalized. </summary>
public readonly int[] Moves;
public readonly ReadOnlySpan<int> Moves;
/// <summary> Level the egg originated at. </summary>
public readonly int Level;
public BreedInfo(int count, Learnset learnset, int[] moves, int level)
public BreedInfo(T[] actual, Span<byte> possible, Learnset learnset, ReadOnlySpan<int> moves, int level)
{
Possible = new byte[count];
Actual = new T[count];
Actual = actual;
Possible = possible;
Learnset = learnset;
Moves = moves;
Level = level;

View file

@ -12,7 +12,7 @@ namespace PKHeX.Core
return valid;
}
public static object Process(int generation, int species, int form, GameVersion version, int[] moves, out bool valid) => generation switch
public static object Process(int generation, int species, int form, GameVersion version, ReadOnlySpan<int> moves, out bool valid) => generation switch
{
2 => MoveBreed2.Validate(species, version, moves, out valid),
3 => MoveBreed3.Validate(species, version, moves, out valid),
@ -29,7 +29,7 @@ namespace PKHeX.Core
return GetExpectedMoves(enc.Generation, enc.Species, enc.Form, enc.Version, moves, parse);
}
public static int[] GetExpectedMoves(int generation, int species, int form, GameVersion version, int[] moves, object parse)
public static int[] GetExpectedMoves(int generation, int species, int form, GameVersion version, ReadOnlySpan<int> moves, object parse)
{
// Try rearranging the order of the moves.
// Build an info table

View file

@ -9,9 +9,9 @@ namespace PKHeX.Core
{
private const int level = 5;
public static EggSource2[] Validate(int species, GameVersion version, int[] moves, out bool valid)
public static EggSource2[] Validate(int species, GameVersion version, ReadOnlySpan<int> moves, out bool valid)
{
var count = Array.IndexOf(moves, 0);
var count = moves.IndexOf(0);
if (count == 0)
{
valid = false; // empty moveset
@ -26,7 +26,9 @@ namespace PKHeX.Core
var pi = table[species];
var egg = (version == GameVersion.C ? Legal.EggMovesC : Legal.EggMovesGS)[species].Moves;
var value = new BreedInfo<EggSource2>(count, learnset, moves, level);
var actual = new EggSource2[count];
Span<byte> possible = stackalloc byte[count];
var value = new BreedInfo<EggSource2>(actual, possible, learnset, moves, level);
{
bool inherit = Breeding.GetCanInheritMoves(species);
MarkMovesForOrigin(value, egg, count, inherit, pi, version);
@ -34,11 +36,11 @@ namespace PKHeX.Core
}
if (!valid)
CleanResult(value.Actual, value.Possible);
return value.Actual;
CleanResult(actual, possible);
return actual;
}
private static void CleanResult(EggSource2[] valueActual, byte[] valuePossible)
private static void CleanResult(EggSource2[] valueActual, Span<byte> valuePossible)
{
for (int i = 0; i < valueActual.Length; i++)
{

View file

@ -13,9 +13,9 @@ namespace PKHeX.Core
{
private const int level = 5;
public static EggSource34[] Validate(int species, GameVersion version, int[] moves, out bool valid)
public static EggSource34[] Validate(int species, GameVersion version, ReadOnlySpan<int> moves, out bool valid)
{
var count = Array.IndexOf(moves, 0);
var count = moves.IndexOf(0);
if (count == 0)
{
valid = false; // empty moveset
@ -30,9 +30,11 @@ namespace PKHeX.Core
var pi = table[species];
var egg = Legal.EggMovesRS[species].Moves;
var value = new BreedInfo<EggSource34>(count, learnset, moves, level);
var actual = new EggSource34[count];
Span<byte> possible = stackalloc byte[count];
var value = new BreedInfo<EggSource34>(actual, possible, learnset, moves, level);
if (species is (int)Species.Pichu && moves[count - 1] is (int)Move.VoltTackle && version == GameVersion.E)
value.Actual[--count] = VoltTackle;
actual[--count] = VoltTackle;
if (count == 0)
{
@ -46,11 +48,11 @@ namespace PKHeX.Core
}
if (!valid)
CleanResult(value.Actual, value.Possible);
CleanResult(actual, possible);
return value.Actual;
}
private static void CleanResult(EggSource34[] valueActual, byte[] valuePossible)
private static void CleanResult(EggSource34[] valueActual, Span<byte> valuePossible)
{
for (int i = 0; i < valueActual.Length; i++)
{

View file

@ -14,9 +14,9 @@ namespace PKHeX.Core
{
private const int level = 1;
public static EggSource34[] Validate(int species, GameVersion version, int[] moves, out bool valid)
public static EggSource34[] Validate(int species, GameVersion version, ReadOnlySpan<int> moves, out bool valid)
{
var count = Array.IndexOf(moves, 0);
var count = moves.IndexOf(0);
if (count == 0)
{
valid = false; // empty moveset
@ -31,9 +31,11 @@ namespace PKHeX.Core
var pi = table[species];
var egg = (version is HG or SS ? Legal.EggMovesHGSS : Legal.EggMovesDPPt)[species].Moves;
var value = new BreedInfo<EggSource34>(count, learnset, moves, level);
var actual = new EggSource34[count];
Span<byte> possible = stackalloc byte[count];
var value = new BreedInfo<EggSource34>(actual, possible, learnset, moves, level);
if (species is (int)Species.Pichu && moves[count - 1] is (int)Move.VoltTackle)
value.Actual[--count] = VoltTackle;
actual[--count] = VoltTackle;
if (count == 0)
{
@ -47,11 +49,11 @@ namespace PKHeX.Core
}
if (!valid)
CleanResult(value.Actual, value.Possible);
CleanResult(actual, possible);
return value.Actual;
}
private static void CleanResult(EggSource34[] valueActual, byte[] valuePossible)
private static void CleanResult(EggSource34[] valueActual, Span<byte> valuePossible)
{
for (int i = 0; i < valueActual.Length; i++)
{

View file

@ -13,9 +13,9 @@ namespace PKHeX.Core
{
private const int level = 1;
public static EggSource5[] Validate(int species, GameVersion version, int[] moves, out bool valid)
public static EggSource5[] Validate(int species, GameVersion version, ReadOnlySpan<int> moves, out bool valid)
{
var count = Array.IndexOf(moves, 0);
var count = moves.IndexOf(0);
if (count == 0)
{
valid = false; // empty moveset
@ -30,9 +30,11 @@ namespace PKHeX.Core
var pi = table[species];
var egg = Legal.EggMovesBW[species].Moves;
var value = new BreedInfo<EggSource5>(count, learnset, moves, level);
var actual = new EggSource5[count];
Span<byte> possible = stackalloc byte[count];
var value = new BreedInfo<EggSource5>(actual, possible, learnset, moves, level);
if (species is (int)Species.Pichu && moves[count - 1] is (int)Move.VoltTackle)
value.Actual[--count] = VoltTackle;
actual[--count] = VoltTackle;
if (count == 0)
{
@ -46,11 +48,11 @@ namespace PKHeX.Core
}
if (!valid)
CleanResult(value.Actual, value.Possible);
CleanResult(actual, possible);
return value.Actual;
}
private static void CleanResult(EggSource5[] valueActual, byte[] valuePossible)
private static void CleanResult(EggSource5[] valueActual, Span<byte> valuePossible)
{
for (int i = 0; i < valueActual.Length; i++)
{

View file

@ -13,9 +13,9 @@ namespace PKHeX.Core
{
private const int level = 1;
public static EggSource6[] Validate(int generation, int species, int form, GameVersion version, int[] moves, out bool valid)
public static EggSource6[] Validate(int generation, int species, int form, GameVersion version, ReadOnlySpan<int> moves, out bool valid)
{
var count = Array.IndexOf(moves, 0);
var count = moves.IndexOf(0);
if (count == 0)
{
valid = false; // empty moveset
@ -30,9 +30,11 @@ namespace PKHeX.Core
var learnset = learn[index];
var egg = MoveEgg.GetEggMoves(generation, species, form, version);
var value = new BreedInfo<EggSource6>(count, learnset, moves, level);
var actual = new EggSource6[count];
Span<byte> possible = stackalloc byte[count];
var value = new BreedInfo<EggSource6>(actual, possible, learnset, moves, level);
if (species is (int)Species.Pichu && moves[count - 1] is (int)Move.VoltTackle)
value.Actual[--count] = VoltTackle;
actual[--count] = VoltTackle;
if (count == 0)
{
@ -46,11 +48,11 @@ namespace PKHeX.Core
}
if (!valid)
CleanResult(value.Actual, value.Possible);
CleanResult(actual, possible);
return value.Actual;
}
private static void CleanResult(EggSource6[] valueActual, byte[] valuePossible)
private static void CleanResult(EggSource6[] valueActual, Span<byte> valuePossible)
{
for (int i = 0; i < valueActual.Length; i++)
{