.agents/skills/performance-fixer/references/bcl-patterns/memory-and-buffers.md
Removing allocations and copies in the managed layer — the lowest-risk, highest-frequency win.
Prefer a shared helper where one exists (../repo-helpers.md). Prove no
allocation regression with [MemoryDiagnoser] (../measuring.md).
stackalloc + Span<T> for small transient buffersSpan<T> tmp = n <= cap ? stackalloc T[n] : ...; for short-lived scratch (≤ ~256–1024
bytes) you write before reading. Pair with [SkipLocalsInit] on the method to skip zeroing.new T[n] for a temporary (e.g. SKPath.GetLine allocates new SKPoint[2]).stackalloc inside a loop or with unbounded n — that
is a stack-overflow crash, not a slowdown. Above the cap, fall back to ArrayPool/heap.ArrayPool<T> / Utils.RentArray for medium/large transient buffersUtils.RentArray<T>(n) (the repo's ArrayPool ref-struct wrapper) or
ArrayPool<T>.Shared; return in a using/finally. Use Utils.RentHandlesArray for IntPtr[]
of wrapper handles.new T[n] / objects.Select(o => o.Handle).ToArray() per call.RentedArray for glyph positions.stackalloc).MemoryMarshal.Cast / AsBytes for blittable reinterpretMemoryMarshal.Cast<uint, SKColor>(span) to view blittable data as another type with no
copy when layouts match (pixel/color paths).System.Memory) · ABI: internal.bool/reference fields,
no platform packing). Verify before casting; a property that promised an independent copy must
keep returning one.in / ref readonly to avoid struct copiesSKMatrix 36 bytes, SKMatrix44, SKSamplingOptions,
GR*Info) by in through internal helpers and new overloads. SkiaSharp already uses
in SKMatrix on canvas draws.in is a signature change — additive overloads / internal only.in a struct the method mutates (or that reintroduces a defensive copy).params ReadOnlySpan<T> overloads (net9 / C# 13)DrawPoints(params ReadOnlySpan<SKPoint>) convenience overloads that avoid the
implicit params T[] heap array.params T[].