From wpf-dev-pack
Implements zero-allocation patterns in .NET using Span, ArrayPool, and ObjectPool to reduce GC pressure in high-performance memory operations.
npx claudepluginhub christian289/dotnet-with-claudecode --plugin wpf-dev-packThis skill uses the workspace's default tool permissions.
A guide for APIs that minimize GC pressure and enable high-performance memory management.
Generates design tokens/docs from CSS/Tailwind/styled-components codebases, audits visual consistency across 10 dimensions, detects AI slop in UI.
Records polished WebM UI demo videos of web apps using Playwright with cursor overlay, natural pacing, and three-phase scripting. Activates for demo, walkthrough, screen recording, or tutorial requests.
Delivers idiomatic Kotlin patterns for null safety, immutability, sealed classes, coroutines, Flows, extensions, DSL builders, and Gradle DSL. Use when writing, reviewing, refactoring, or designing Kotlin code.
A guide for APIs that minimize GC pressure and enable high-performance memory management.
Quick Reference: See QUICKREF.md for essential patterns at a glance.
| API | Purpose | NuGet |
|---|---|---|
Span<T>, Memory<T> | Stack-based memory slicing | BCL |
ArrayPool<T>.Shared | Reduce GC pressure through array reuse | BCL |
DefaultObjectPool<T> | Object pooling | Microsoft.Extensions.ObjectPool |
MemoryCache | In-memory caching | System.Runtime.Caching |
// Zero Allocation when parsing strings
public void ParseData(ReadOnlySpan<char> input)
{
// String manipulation without Heap allocation
var firstPart = input.Slice(0, 10);
var secondPart = input.Slice(10);
}
// Array slicing
public void ProcessArray(int[] data)
{
Span<int> span = data.AsSpan();
Span<int> firstHalf = span[..^(span.Length / 2)];
Span<int> secondHalf = span[(span.Length / 2)..];
}
// ❌ Bad example: Substring allocates new string
string part = text.Substring(0, 10);
// ✅ Good example: AsSpan has no allocation
ReadOnlySpan<char> part = text.AsSpan(0, 10);
public void ProcessSmallBuffer()
{
// Allocate small buffer on Stack (no Heap allocation)
Span<byte> buffer = stackalloc byte[256];
FillBuffer(buffer);
}
Reduces GC pressure by reusing large arrays.
namespace MyApp.Services;
public sealed class DataProcessor
{
public void ProcessLargeData(int size)
{
// Rent array (minimize Heap allocation)
var buffer = ArrayPool<byte>.Shared.Rent(size);
try
{
// Use buffer (only use up to requested size)
ProcessBuffer(buffer.AsSpan(0, size));
}
finally
{
// Must return
ArrayPool<byte>.Shared.Return(buffer);
}
}
}
// Initialize before returning when handling sensitive data
ArrayPool<byte>.Shared.Return(buffer, clearArray: true);
Reuses expensive objects.
namespace MyApp.Services;
using Microsoft.Extensions.ObjectPool;
public sealed class HeavyObjectProcessor
{
private readonly ObjectPool<HeavyObject> _pool;
public HeavyObjectProcessor()
{
var policy = new DefaultPooledObjectPolicy<HeavyObject>();
_pool = new DefaultObjectPool<HeavyObject>(policy, maximumRetained: 100);
}
public void Process()
{
var obj = _pool.Get();
try
{
obj.DoWork();
}
finally
{
_pool.Return(obj);
}
}
}
Unlike Span, can be stored in fields or used in async methods.
public sealed class AsyncProcessor
{
private Memory<byte> _buffer;
public AsyncProcessor(int size)
{
_buffer = new byte[size];
}
// Memory<T> can be used in async methods
public async Task ProcessAsync()
{
await FillBufferAsync(_buffer);
ProcessData(_buffer.Span);
}
}
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.ObjectPool" Version="9.0.*" />
</ItemGroup>
Span<T>, ReadOnlySpan<T> cannot be used with async-awaitRent() must be returned with Return()// Array larger than requested may be returned
var buffer = ArrayPool<byte>.Shared.Rent(100);
// buffer.Length >= 100 (not exactly 100)
// Use only requested size when actually using
ProcessBuffer(buffer.AsSpan(0, 100));