ioxide 0.0.7
See the version list below for details.
dotnet add package ioxide --version 0.0.7
NuGet\Install-Package ioxide -Version 0.0.7
<PackageReference Include="ioxide" Version="0.0.7" />
<PackageVersion Include="ioxide" Version="0.0.7" />
<PackageReference Include="ioxide" />
paket add ioxide --version 0.0.7
#r "nuget: ioxide, 0.0.7"
#:package ioxide@0.0.7
#addin nuget:?package=ioxide&version=0.0.7
#tool nuget:?package=ioxide&version=0.0.7
A shared-nothing io_uring runtime for .NET.
One ring per reactor thread - run one per core. HTTP, Postgres, and file I/O submit on that ring and resume inline on the same thread. No thread pool on the hot path. No native dependencies - raw syscalls, nothing else.
Linux 6.1+ · .NET 10 · status
0.0.5- experimental
Documentation - architecture, guides, the full picture
Quick start
dotnet run -c Release --project Playground # GET / → ok
PLAYGROUND_MODE=pg dotnet run -c Release --project Playground # SELECT 42 over the ring
PLAYGROUND_MODE=file dotnet run -c Release --project Playground # static files off the ring
How it works
var reactor = new Reactor(id, new ServerConfig { Port = 8080 });
// Clients opened here ride this reactor's ring.
reactor.OnStart = r => PgPool.Start(r, pgOptions);
reactor.Handle = async (r, conn) =>
{
var pool = r.GetService<PgPool>();
// Carry for bytes a read leaves behind - the head of a split request.
var inflight = new byte[16 * 1024];
int inflightTail = 0;
while (true)
{
// io_uring recv - resumes inline on the reactor.
var snapshot = await conn.ReadAsync();
var rings = conn.GetSnapshotMemories(snapshot);
if (rings.Length > 0)
{
ReadOnlySequence<byte> data;
if (inflightTail == 0 && rings.Length == 1)
{
// Hot path: one ring, no carry - a single zero-copy segment.
data = new ReadOnlySequence<byte>(rings[0].Memory);
}
else if (inflightTail == 0)
{
// Several rings, no carry - chain them, still zero-copy.
data = rings.ToReadOnlySequence();
}
else
{
// Cold path: the carry goes first so a split request reads whole.
var first = new RingSegment(inflight.AsMemory(0, inflightTail), 0);
var last = first;
for (int i = 0; i < rings.Length; i++)
last = last.Append(rings[i].Memory, rings[i].BufferId);
data = new ReadOnlySequence<byte>(first, 0, last, last.Memory.Length);
}
// Walk every complete request; stop at the first partial one.
// TryParseRequest, Request, and SqlFor are YOUR code - ioxide
// hands you raw bytes and stays out of HTTP.
long consumed = 0;
bool respond = false;
while (TryParseRequest(data.Slice(consumed), out Request request, out long length))
{
consumed += length;
// io_uring send + recv to Postgres, on the same ring.
var rows = await pool.QueryAsync(SqlFor(request.Path));
// ioxide doesn't speak HTTP for you - you write the bytes.
string body = $"db={rows.Value}";
conn.Write(Encoding.ASCII.GetBytes(
$"HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: {body.Length}\r\n\r\n{body}"));
respond = true;
}
// Whatever wasn't consumed (a partial request, or everything when
// nothing completed) moves to the front of the carry - only then
// do the buffers go back to the ring.
ReadOnlySequence<byte> rest = data.Slice(consumed);
rest.CopyTo(inflight);
inflightTail = (int)rest.Length;
conn.ReturnBuffers(rings);
if (respond) await conn.FlushAsync(); // io_uring send, once per batch
}
if (snapshot.IsClosed)
{
conn.DecRef();
return;
}
conn.ResetRead();
}
};
// One reactor per core.
new Thread(reactor.Run).Start();
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net11.0 is compatible. |
-
net11.0
- No dependencies.
NuGet packages (7)
Showing the top 5 NuGet packages that depend on ioxide:
| Package | Downloads |
|---|---|
|
ioxide.pg
Postgres driver for the ioxide io_uring runtime: pooled ring-native connections per reactor, ring-native connect and handshake, inline completion resume. |
|
|
ioxide.file
File serving for the ioxide io_uring runtime: immutable asset snapshots with baked responses, pooled positional ring reads, atomic reloads. |
|
|
ioxide.tls
TLS for the ioxide io_uring runtime: OpenSSL handshake driven over the ring, then kernel TLS (kTLS) transmit offload - handlers keep writing plaintext through the same connection API. Requires Linux kTLS (tls module) and OpenSSL 3. |
|
|
ioxide.redis
Redis client for the ioxide io_uring runtime: pooled ring-native connections per reactor, full RESP2 protocol, a generic command API plus typed helpers (strings, keys, hashes, lists, sets, sorted sets, pub/sub, transactions, scripting), and pipelining. Inline completion resume. |
|
|
ioxide.Kestrel
ASP.NET Core Kestrel transport backed by the ioxide io_uring runtime: one reactor (ring) per core, SO_REUSEPORT load-balanced, with Kestrel's HTTP request loop pinned to the reactor thread. Drop-in via UseIoxide(). |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.0.17 | 165 | 6/23/2026 |
| 0.0.16 | 100 | 6/21/2026 |
| 0.0.15 | 96 | 6/21/2026 |
| 0.0.14 | 101 | 6/21/2026 |
| 0.0.13 | 104 | 6/21/2026 |
| 0.0.12 | 155 | 6/21/2026 |
| 0.0.11 | 130 | 6/20/2026 |
| 0.0.10 | 100 | 6/20/2026 |
| 0.0.9 | 97 | 6/20/2026 |
| 0.0.8 | 121 | 6/19/2026 |
| 0.0.7 | 108 | 6/17/2026 |
| 0.0.6 | 158 | 6/15/2026 |
| 0.0.5 | 183 | 6/13/2026 |
| 0.0.4 | 142 | 6/12/2026 |
| 0.0.3 | 136 | 6/12/2026 |
| 0.0.2 | 141 | 6/11/2026 |
| 0.0.1 | 117 | 6/11/2026 |