Calling stackalloc in a loop leads to stack overflow. This bug is easy to introduce with the above.
Category: Performance
Examples of patterns to report on
For loop, iteration count is non-constant
private int SomeMethod(ReadOnlySpan<byte> source, Span<byte> destination)
{
int writeOffset = 0;
for (int i = 0; i < source.Length; i += ChunkSize)
{
Span<byte> tmp = stackalloc byte[32];
writeOffset += CRC32(
source.Slice(i, Math.Min(source.Length - i, ChunkSize)),
tmp);
WriteReversed(tmp, destination.Slice(writeOffset));
}
return writeOffset;
}
While loop, non-constant iteration count:
private int SomeMethod(ReadOnlySpan<byte> source, Span<byte> destination)
{
int writeOffset = 0;
while (!source.IsEmpty)
{
Span<byte> tmp = stackalloc byte[32];
ReadOnlySpan<byte> cur = source.Length < ChunkSize ? source : source.Slice(0, ChunkSize);
writeOffset += CRC32(cur, tmp);
WriteReversed(tmp, destination.Slice(writeOffset));
source = source.Slice(cur.Length);
}
return writeOffset;
}
(Also do/while, and foreach)
Examples of patterns to not report on
This method always has the same sized stackalloc.
It could be used more efficiently, but it's deterministic, so it's not worth reporting on.
private int SomeMethod(ReadOnlySpan<byte> source, Span<byte> destination)
{
for (int i = 0; i < 4; i++)
{
Span<byte> tmp = stackalloc byte[32];
CRC32(source.Slice(i), tmp);
WriteReversed(tmp, destination.Slice(i));
}
return 35;
}
Stackalloc is in a loop, but it only ever runs on one iteration:
private int SomeMethod(ReadOnlySpan<byte> source, Span<byte> destination)
{
for (int i = 1; i < source.Length; i++)
{
if (source[i - 1] + source[i] > 202)
{
Span<byte> tmp = stackalloc byte[32];
CRC32(source.Slice(i+1), tmp);
WriteReversed(tmp, destination);
return 32;
}
}
return 0;
}
Same idea, different shape.
private int SomeMethod(Span<byte> destination)
{
int accum = 0;
while (true)
{
ReadOnlySpan<byte> next = GetNextData();
for (int i = 0; i < next.Length; i++)
{
accum += next[i];
}
int popCount = PopCount(accum);
if (popCount > 2 && popCount < 6)
{
if (_reversed)
{
Span<byte> tmp = stackalloc byte[32];
CRC32(accum.AsBytes(), tmp);
WriteReversed(tmp, destination);
}
else
{
CRC32(accum.AsBytes(), destination);
}
break;
}
}
return 32;
}
Calling stackalloc in a loop leads to stack overflow. This bug is easy to introduce with the above.
Category: Performance
Examples of patterns to report on
For loop, iteration count is non-constant
While loop, non-constant iteration count:
(Also do/while, and foreach)
Examples of patterns to not report on
This method always has the same sized stackalloc.
It could be used more efficiently, but it's deterministic, so it's not worth reporting on.
Stackalloc is in a loop, but it only ever runs on one iteration:
Same idea, different shape.