Fix LineCanvas.GetMap per-pixel allocations by reusing buffer

Applied the same allocation-free pattern from GetCellMap() to GetMap():
- Reuse List<IntersectionDefinition> buffer instead of LINQ .ToArray()
- Use CollectionsMarshal.AsSpan() to create ReadOnlySpan
- Eliminates 1,920+ allocations per border redraw (80x24)
- Reduces from O(pixels) allocations to 1 allocation total

All unit tests pass (12,055 parallelizable + 1,173 non-parallel)

Co-authored-by: tig <585482+tig@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2025-12-03 19:02:44 +00:00
parent d21163e394
commit a4245bd091

View File

@@ -211,15 +211,23 @@ public class LineCanvas : IDisposable
{
Dictionary<Point, Rune> map = new ();
List<IntersectionDefinition> intersectionsBufferList = [];
// walk through each pixel of the bitmap
for (int y = inArea.Y; y < inArea.Y + inArea.Height; y++)
{
for (int x = inArea.X; x < inArea.X + inArea.Width; x++)
{
IntersectionDefinition [] intersects = _lines
.Select (l => l.Intersects (x, y))
.OfType<IntersectionDefinition> () // automatically filters nulls and casts
.ToArray ();
intersectionsBufferList.Clear ();
foreach (var line in _lines)
{
if (line.Intersects (x, y) is { } intersect)
{
intersectionsBufferList.Add (intersect);
}
}
// Safe as long as the list is not modified while the span is in use.
ReadOnlySpan<IntersectionDefinition> intersects = CollectionsMarshal.AsSpan(intersectionsBufferList);
Rune? rune = GetRuneForIntersects (intersects);