optimizing-memory-allocation — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited optimizing-memory-allocation (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
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<T>, 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));~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.