SharpArena 0.7.19

dotnet add package SharpArena --version 0.7.19
                    
NuGet\Install-Package SharpArena -Version 0.7.19
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="SharpArena" Version="0.7.19" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SharpArena" Version="0.7.19" />
                    
Directory.Packages.props
<PackageReference Include="SharpArena" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add SharpArena --version 0.7.19
                    
#r "nuget: SharpArena, 0.7.19"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package SharpArena@0.7.19
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=SharpArena&version=0.7.19
                    
Install as a Cake Addin
#tool nuget:?package=SharpArena&version=0.7.19
                    
Install as a Cake Tool

SharpArena

Zero-alloc arena allocator + collections for high-perf parsers.

This is a pet project originally written for a JsonPath parser as a challenge, but I decided to keep it as a separate lib because I think it's useful.

Samples

Check out the samples directory for complete, end-to-end examples of building a math expression parser with zero managed allocations (outside the arena). Now with Blazor WebAssembly demo — zero managed allocations in the browser

  • SimpleMathParser Try SimpleMathParser: A standard .NET console app using ArenaList, ArenaPtrStack, and ArenaString to tokenize and evaluate expressions.
  • BlazorMathSymbolicCalculator Try BlazorMathSymbolicCalculator: A symbolic calculator Blazor WebAssembly app evaluating math equations in-browser natively without garbage collection.

Reusable Parser Example

The ArenaMathParser extracted for the above samples showcases reusing arena allocations efficiently:

using SharpArena.Allocators;

using var arena = new ArenaAllocator();

// Tokenize the mathematical string into unmanaged tokens inside the arena
var tokens = ArenaMathParser.Tokenize("2 + 3 * x".Replace("x", "10"), arena);

// Evaluate safely allocating on the unmanaged stack internally
double result = ArenaMathParser.Evaluate(tokens, arena);

// Resets pointers and drops all tokens without GC involvement
arena.Reset();

Usage

using SharpArena.Allocators;

using var arena = new ArenaAllocator();
// Memory allocated from arena, invalid after arena is Reset or Disposed
var ptr = arena.Alloc(1024);
arena.Reset();

Collections

SharpArena includes several collection types designed to be backed by the arena allocator. These collections allocate memory from the arena and become invalid when the arena is reset or disposed. They avoid normal GC allocations.

ArenaString

A non-owning view of UTF-16 text stored in unmanaged (arena) memory.

using SharpArena.Collections;

// Clone a managed string or span into the arena
var str = ArenaString.Clone("Hello, World!", arena);

// Can be implicitly cast to ReadOnlySpan<char>
ReadOnlySpan<char> span = str;

// Or explicitly converted back to a managed string
Console.WriteLine(str.ToString());

ArenaString equality and hash codes are both content-based (character data + length), so separately cloned but equal text compares and hashes the same. When to use: Use ArenaString when you need to store substrings, tokens, or parsed text during parsing or processing without creating System.String allocations for every token.

ArenaList

A dynamic array (list) backed by the arena for unmanaged structs.

using SharpArena.Collections;

var list = new ArenaList<int>(arena, initialCapacity: 16);
list.Add(1);
list.Add(2);
list.Add(3);

foreach (var item in list.AsSpan()) {
    Console.WriteLine(item);
}

When to use: Use ArenaList<T> when you need a fast, resizable list of items (like AST nodes or tokens) during a single operation, avoiding GC overhead for arrays.

Note on growth: When dynamic collections like ArenaList double in size, they allocate a new buffer and leave the old buffer alive until Reset() is called. This is fine for short-lived arenas, but if you do a lot of growing in one operation, you're temporarily burning memory that could have been reused. This is a classic bump-allocator edge case.

ArenaPtrStack

A fast, unmanaged stack specifically for pointers.

using SharpArena.Collections;

var stack = new ArenaPtrStack<int>(arena, initialCapacity: 16);
int a = 42;
stack.Push(&a);

var ptr = stack.Pop();
Console.WriteLine(*ptr);

When to use: Use ArenaPtrStack<T> when writing parsers or state machines that need to push and pop pointers to unmanaged memory rapidly.

Comparison with Varena

Varena is another excellent arena allocator library for .NET. Here is a quick comparison to help you choose:

SharpArena

  • Internal workings: Uses a linked list of segments (ArenaSegment), dynamically allocating memory via NativeMemory or P/Invoke as needed. Memory is requested in chunks and bumped within the active segment.
  • Limitations: Over-allocates slightly if many small objects are allocated, since segment sizes double up to a maximum. Requires careful management of unmanaged memory since there are no GC roots.
  • When to use: Best for fast parsing scenarios (like parsers or temporary request states) where you want to allocate a batch of objects, possibly strings or lists, and drop them all at once. Includes built-in collections.

Varena

  • Internal workings: Leverages virtual memory directly (e.g., VirtualAlloc on Windows). It reserves a massive contiguous virtual address space upfront and commits physical memory pages strictly as needed.
  • Limitations: Not available in WASM environments because it requires virtual memory OS APIs.
  • When to use: Better when you need to continuous blocks of very large memory without worrying about re-allocations or segment limits, and you are on a supported platform (Windows/Linux/macOS).

Thread Safety

SharpArena is strictly NOT thread-safe.

To achieve maximum performance and zero overhead on the hot path, ArenaAllocator and its associated collections do not use any synchronization primitives (locks, interlocked operations, or volatile reads).

  • One Arena Per Thread: You should create a separate ArenaAllocator instance for each thread or use a [ThreadStatic] field.
  • No Concurrent Access: Do not call Alloc, Reset, or Dispose concurrently from multiple threads on the same instance.
  • Single-Threaded Collections: Collections like ArenaList<T> and ArenaString are intended to be used within the same thread that owns the arena.

Benchmarks

See bench/ArenaBench.md for performance numbers compared to NativeMemory and Varena.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.7.19 21 3/21/2026
0.7.18 19 3/21/2026
0.7.17 18 3/21/2026
0.7.16 19 3/21/2026
0.7.15 18 3/21/2026
0.7.14 96 3/16/2026
0.7.13 84 3/16/2026
0.7.12 82 3/16/2026
0.7.11 91 3/15/2026
0.7.10 76 3/15/2026
0.7.9 83 3/15/2026
0.7.8 86 3/15/2026
0.7.7 85 3/14/2026
0.7.6 88 3/14/2026
0.7.5 91 3/14/2026
0.7.4 159 3/14/2026
0.7.3 87 3/14/2026
0.7.2 87 3/14/2026
0.7.1 90 3/14/2026
0.7.0 86 3/14/2026
Loading failed

- test: add happy path tests for ArenaBlockList<T>.GetSpan()