The fastest binary serializer for C#.
Source-generated, zero-allocation, thread-safe and safe on untrusted input.
For .NET, Unity, Godot and HybridCLR, with the same bytes on every platform and runtime, Go, Rust and TypeScript included.
🌐 Website · 🚀 Getting Started · What's new in v4 · Benchmarks · 中文
- Fastest. Up to 7.2× faster serialization than MemoryPack, and up to 9.5× faster deserialization into existing objects. Benchmarks
- Safe on untrusted input. Crafted bytes cannot crash the process, read past the input, allocate out of proportion
or name a type to create; every invalid input throws one
NinoDataException. Untrusted data - Zero allocation. Serialize into an
IBufferWriter<byte>, deserialize into existing or pooled objects: nothing allocated per call, thread-safe, with no locks on the hot path. Zero allocation - Everything at compile time. No reflection, no IL emit, no registration, no init call: works on IL2CPP, Native AOT and HybridCLR hot updates, and compiles up to 221× faster than v3. Platforms
- The same bytes everywhere. Identical bytes on every runtime and CPU, and from Go, Rust and TypeScript through the
code
nino-genwrites for your types. Other languages - Rich types that evolve. Polymorphism without tags, keyed and version-tolerant types, reference tracking, every BCL collection. Supported types
- Mistakes caught as you type. 33 analyzer diagnostics, many with a one-click fix. Analyzers
dotnet add package Nino --prerelease # .NET and Godot: the runtime and the generator
openupm add com.jasonxudeveloper.nino # Unity 2022.3+Nino v4 is a prerelease, so --prerelease is required: without it NuGet installs 3.9.x, which cannot read or write v4
data. Optional packages: Nino.Immutable (System.Collections.Immutable), Nino.AspNetCore (MVC formatters, Minimal API
bodies and results), Nino.Codegen (your types as TypeScript, Go or Rust after each build; Nino.Codegen.Tool is the
same as the nino-gen command). Installation for .NET, Unity and Godot.
using Nino.Core;
[NinoType]
public sealed class Order
{
public long Id;
public string Customer;
public List<OrderLine> Lines;
}
byte[] bytes = NinoSerializer.Serialize(order);
Order copy = NinoDeserializer.Deserialize<Order>(bytes);
NinoDeserializer.Deserialize(bytes, ref copy); // fills the same instance in placePolymorphism needs no tags: a value declared as its base is read back as its runtime type.
[NinoType] public abstract class Message { public int Seq; }
[NinoType] public sealed class Chat : Message { public string Text; }
byte[] bytes = NinoSerializer.Serialize<Message>(new Chat { Text = "hi" });
Message msg = NinoDeserializer.Deserialize<Message>(bytes); // a Chat againNext: your first types, evolving data, reference tracking, pooling and the advanced guides.
Nino ships a skill for Claude Code, Codex, Cursor, Copilot and other agents:
npx skills add JasonXuDeveloper/NinoThe nino-serialization skill teaches your assistant to declare [NinoType]s, pick the format for data that
outlives a release, use the fast and zero-allocation forms, and fix every NINO diagnostic. The docs are written for
models too: llms.txt, llms-full.txt, and
every page as Markdown (add .md to its URL).
BenchmarkDotNet 0.15.8, .NET 10.0.14, server GC, Intel Xeon 6973P-C 3.54 GHz; Nino v4 and MemoryPack 1.21.4 in one run, Nino 3.3.13 from NuGet directly before it on the same machine. Payloads are about the same size (SimpleClass: 1,069 bytes in v4, 1,152 in v3, 1,148 in MemoryPack). Every case and the method: docs/v4-benchmarks.md; the notes of each release carry that release's numbers.
Every case, Arm64, MessagePack and protobuf-net: .NET benchmarks; Unity with Burst; Go, Rust and TypeScript. Arrays of tuples and structs and string conversion use AVX-512, AVX2, SSSE3, Arm64 and WebAssembly SIMD (Burst kernels in Unity), with portable code writing the same bytes elsewhere: SIMD.
| ⚙️ Services & IPC | No per-call allocations, safe concurrent use; ASP.NET Core bodies as application/x-nino. |
| 🌐 RPC & networking | Straight into a PipeWriter, pooled messages, and a crafted message throws instead of taking the server down. |
| 📨 Message queues · 🗄️ Caching · 💾 Storage | Polymorphic events, small payloads, and formats that let fields be added, reordered and removed across releases. |
| 🧩 Web, Node, Go & Rust | Types and codecs generated after each build, so browsers and services read and write the same bytes as .NET. |
| 🎮 Unity | 2022.3+, Mono and IL2CPP, HybridCLR without an init call, Burst SIMD kernels, AnimationCurve and Gradient built in. |
| 👾 Godot 4 (.NET) | A regular NuGet package; Vector3, Transform3D and other math structs are copied as raw memory. |
MemoryPack's README now calls it "a high-performance serialization format for trusted data only" (MemoryPack README); Nino is built for data from network peers and user files (details).
| Nino v4 | MemoryPack 1.21.4 | |
|---|---|---|
| Untrusted input | built for it: bounded allocation and stack, one exception type | trusted data only, per its README |
| Serialize classes and polymorphic types | 3.5–7.2× faster | |
| Deserialize classes and polymorphic types | 1.7–2.1× faster | |
| Raw struct arrays | at least on par without padding (a block copy in both); padding zeroed | padding copied as is, in the platform's layout |
| Deserialize into existing objects | 0 B, up to 9.5× faster (in place) | overwrite mode: clears collections and allocates their elements again |
| Polymorphism | automatic type ids, any base class or interface, generic bases included | [MemoryPackUnion] tags you maintain, not on generic types |
| Keyed members, reference tracking, object pools | ✅ | version tolerance and circular references, no pools |
| Unity | ✅ 2022.3+, one OpenUPM package, netstandard2.0 and 2.1 |
✅ 2022.3.12f1+, NuGetForUnity plus a git package, netstandard2.1 |
While benchmarking we found three types MemoryPack 1.21.4 does not round-trip (BigInteger, BitArray on .NET 10,
tuples between runtimes); Nino writes them by value. The full comparison
covers them, what MemoryPack has that Nino does not, and how to switch. Also compared:
MessagePack and
protobuf-net.
v4 is a rewrite of the runtime and the generator. Its binary format is not compatible with v3.
| v4 vs v3 (3.3.13) | |
|---|---|
| Serialize | 2.11× faster (class), 2.49× faster (class array), 1.37× faster (struct), on par (struct array) |
| Deserialize | 1.55× faster (class), 1.55× faster (class array), on par (struct), on par (struct array), while adding reference tracking, reuse deserialization and payload validation |
| Compiling the generated code | 51× faster at 330 types (42.9 s → 0.84 s), 221× faster at 1,100 types (462 s → 2.1 s) |
| Running the generator | 3.1× faster; after an edit, only that type is re-generated (8.3× faster) |
| Generated code | 14× smaller source, 5× smaller IL |
Everything new: what's new in v4, the changelog and the migration guide; internals are in docs/v4-design.md.
Issues and pull requests are welcome. CONTRIBUTING.md covers building, the test matrix and releasing.
MIT License · Made by JasonXuDeveloper
