Cysharp/MemoryPack
Zero encoding extreme performance binary serializer for C# and Unity.
Healthy across the board
Permissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 4w ago
- ✓12 active contributors
- ✓Distributed ownership (top contributor 36% of recent commits)
Show 3 more →Show less
- ✓MIT licensed
- ✓CI configured
- ✓Tests present
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/cysharp/memorypack)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/cysharp/memorypack on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: Cysharp/MemoryPack
Generated by RepoPilot · 2026-05-10 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/Cysharp/MemoryPack shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across the board
- Last commit 4w ago
- 12 active contributors
- Distributed ownership (top contributor 36% of recent commits)
- MIT licensed
- CI configured
- Tests present
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live Cysharp/MemoryPack
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/Cysharp/MemoryPack.
What it runs against: a local clone of Cysharp/MemoryPack — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in Cysharp/MemoryPack | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch main exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 60 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of Cysharp/MemoryPack. If you don't
# have one yet, run these first:
#
# git clone https://github.com/Cysharp/MemoryPack.git
# cd MemoryPack
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of Cysharp/MemoryPack and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "Cysharp/MemoryPack(\\.git)?\\b" \\
&& ok "origin remote is Cysharp/MemoryPack" \\
|| miss "origin remote is not Cysharp/MemoryPack (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
&& ok "license is MIT" \\
|| miss "license drift — was MIT at generation time"
# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
&& ok "default branch main exists" \\
|| miss "default branch main no longer exists"
# 4. Critical files exist
test -f "README.md" \\
&& ok "README.md" \\
|| miss "missing critical file: README.md"
test -f "MemoryPack.sln" \\
&& ok "MemoryPack.sln" \\
|| miss "missing critical file: MemoryPack.sln"
test -f "Directory.Build.props" \\
&& ok "Directory.Build.props" \\
|| miss "missing critical file: Directory.Build.props"
test -f ".github/workflows/build-release.yaml" \\
&& ok ".github/workflows/build-release.yaml" \\
|| miss "missing critical file: .github/workflows/build-release.yaml"
test -f "sandbox/Benchmark/Benchmarks/SerializeTest.cs" \\
&& ok "sandbox/Benchmark/Benchmarks/SerializeTest.cs" \\
|| miss "missing critical file: sandbox/Benchmark/Benchmarks/SerializeTest.cs"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 60 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~30d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/Cysharp/MemoryPack"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
MemoryPack is a zero-encoding binary serializer for C# and .NET that achieves 10-200x performance gains over competitors (System.Text.Json, protobuf-net, MessagePack) by copying C# memory layouts directly rather than encoding/decoding intermediate formats. It uses Incremental Source Generators (.NET 7+, C# 11) for compile-time code generation to serialize/deserialize POCO objects with zero reflection overhead, supporting native AOT, Unity IL2CPP, and modern I/O APIs like IBufferWriter<byte> and ReadOnlySequence<byte>. Single-repository structure with MemoryPack.sln as the entry point. Core logic lives in unshown src/ directories referenced by build props (inferred from Directory.Build.props and .github/workflows). Sandbox/Benchmark/ contains extensive micro-benchmarks (SerializeInt.cs, BlockCopy.cs, Hyper.cs) and macro-benchmarks (SerializeTest.cs, DeserializeTest.cs) against competing serializers. Sandbox/Benchmark/Models/ houses test payloads (BinaryPackModels, JilModels) for comparative measurement. TypeScript support implied by /typescript files for cross-platform code generation.
👥Who it's for
C# backend engineers, game developers using Unity (2021.3+), and performance-critical system developers who need to serialize structured data at extreme speeds without reflection penalties. Specifically: microservice builders handling high-throughput RPC, game networking code, and real-time analytics pipelines.
🌱Maturity & risk
Production-ready and actively maintained. The project has a full CI/CD pipeline (build-debug.yaml, build-release.yaml, dependabot.yaml in .github/workflows/), comprehensive benchmark suite in sandbox/Benchmark/, published on NuGet (v1.21.4 as of the dependency snapshot), and is the 4th serializer by the same author (neuecc) who created MessagePack-CSharp and Utf8Json. Code generation via Source Generators (not IL.Emit) makes it safe for AOT scenarios.
Low risk for core functionality; the library has zero external dependencies (confirmed in package.json and Directory.Build.props context). Main risks: (1) Source Generator adoption requires .NET 5+ minimum (.NET Standard 2.1), limiting legacy .NET Framework usage; (2) Single maintainer (Cysharp/neuecc) concentrates knowledge; (3) Format is proprietary (not a standard like protobuf), so interop with other languages requires custom TypeScript code generation (visible in /typescript files). Breaking changes are possible across major versions since it's still iterating on the format.
Active areas of work
Active maintenance with dependabot automation (dependabot.yaml) for dependency updates and regular CI runs. The benchmark suite is regularly executed (build-debug and build-release workflows), suggesting ongoing performance regression testing. Based on version 1.21.4 in the manifest, incremental feature releases are ongoing, likely focused on additional serializer integrations and performance micro-tuning given the extensive micro-benchmark files (Utf8Decoding.cs, ConcurrentQueueVsStack.cs, StaticAbstractVsFormatter.cs).
🚀Get running
git clone https://github.com/Cysharp/MemoryPack.git
cd MemoryPack
dotnet restore MemoryPack.sln
dotnet build MemoryPack.sln
For benchmarks:
cd sandbox/Benchmark
dotnet run -c Release --project Benchmark.csproj
Daily commands:
# Unit/integration tests (inferred)
dotnet test MemoryPack.sln
# Benchmarks (with real payload models)
cd sandbox/Benchmark
dotnet run -c Release --project Benchmark.csproj -- --filter *SerializeTest*
# Specific micro-benchmarks
dotnet run -c Release --project Benchmark.csproj -- --filter *Utf8Decoding*
🗺️Map of the codebase
README.md— Entry point documenting MemoryPack's zero-encoding approach, performance claims, and usage patterns essential for understanding the project's purpose.MemoryPack.sln— Solution file defining all projects and dependencies; critical for setting up the development environment and understanding the multi-project structure.Directory.Build.props— Centralized build configuration affecting all projects; contains shared properties, NuGet settings, and version management..github/workflows/build-release.yaml— CI/CD pipeline for releases; shows how the serializer is tested, built, and packaged for NuGet distribution.sandbox/Benchmark/Benchmarks/SerializeTest.cs— Core benchmarking suite demonstrating serialization performance against competitors; validates the library's x10+ performance claims.sandbox/SandboxConsoleApp/Program.cs— Minimal working example showing practical usage of MemoryPack serialization API.
🛠️How to make changes
Add a new serialization benchmark
- Create a new benchmark class in sandbox/Benchmark/Benchmarks/ inheriting from SerializerTestBase (
sandbox/Benchmark/Benchmarks/SerializerTestBase.cs) - Add [Benchmark] methods comparing MemoryPack.Serialize<T>() with competitor serializers (
sandbox/Benchmark/Benchmarks/SerializeTest.cs) - Register the new benchmark in the category system using BenchmarkNetUtilities (
sandbox/Benchmark/BenchmarkNetUtilities/Categories.cs) - Run via 'dotnet run -c Release' in sandbox/Benchmark and compare outputs (
sandbox/Benchmark/Program.cs)
Add a new model for serialization testing
- Define the model class in sandbox/Benchmark/Models/ with public properties matching your data structure (
sandbox/Benchmark/Models/MyClass.cs) - Implement IInitializable if needed for test setup, or add test data factory (
sandbox/Benchmark/Models/BinaryPackModels/Interfaces/IInitializable.cs) - Reference the model in benchmark constructors to generate serializers via source generation (
sandbox/Benchmark/Benchmarks/SerializeTest.cs) - Verify serialization round-trips using the model in DeserializeTest (
sandbox/Benchmark/Benchmarks/DeserializeTest.cs)
Integrate MemoryPack into an ASP.NET Core application
- Reference MemoryPack NuGet package in your .csproj and add using MemoryPack; statements (
sandbox/SandboxWebApp/SandboxWebApp.csproj) - Create a controller method returning MemoryPack-serialized objects (see reference implementation) (
sandbox/SandboxWebApp/Controllers/MemoryPackController.cs) - Define your models with public properties; source generator auto-creates MemoryPack serializers (
sandbox/SandboxWebApp/Models.cs) - Optionally configure custom formatters or compression in your Program.cs setup (
sandbox/SandboxConsoleApp/Program.cs)
Validate Native AOT compatibility
- Create a console app targeting net8.0 with PublishAot=true in .csproj (
sandbox/NativeAot/NativeAot.csproj) - Use MemoryPack serialization in Program.Main; source-gen must handle all types at compile-time (
sandbox/NativeAot/Program.cs) - Run 'dotnet publish -c Release' and verify binary runs without JIT (
sandbox/NativeAot/NativeAot.csproj)
🔧Why these technologies
- C# Source Generators (Roslyn) — Compile-time code generation produces serializers tailored to each type, eliminating runtime reflection overhead and enabling Native AOT compatibility.
- Span<T> & Memory<T> — Zero-copy buffer semantics allow direct memory access without marshaling or encoding/decoding passes, achieving x10 performance gains over traditional serializers.
- BenchmarkDotNet — Rigorous micro-benchmarking framework validates performance claims with statistical significance across competing serializers.
- Native AOT (.NET 8+) — Demonstrates compatibility with trimming and AOT compilation, enabling high-performance server and embedded scenarios.
⚖️Trade-offs already made
-
Source generation (compile-time) vs runtime reflection
- Why: Eliminates per-serialization reflection overhead and enables ahead-of-time analysis for optimization.
- Consequence: Requires explicit type registration or attributes; cannot serialize truly dynamic or unvetted types at runtime.
-
Zero-copy semantics via struct pinning instead of full object copying
- Why: Achieves extreme performance and minimal GC pressure by reusing buffer memory.
- Consequence: Requires careful lifetime management; buffers must not be deallocated while deserialized objects are in use (trade-off vs safety).
-
Binary format over human-readable text (JSON/XML)
- Why: Reduces payload size (2–5x smaller) and eliminates encoding/decoding passes.
- Consequence: Serialized data is opaque to inspection; requires version-tolerance mechanisms for schema evolution.
-
Struct array specialization with bulk copy
- Why: Achieves x50+ speedup for homogeneous collections by directly copying memory.
- Consequence: Only applicable to blittable types; complex nested structures cannot use this optimization.
🚫Non-goals (don't propose these)
- Does not provide human-readable output; intended for binary wire protocols, not debugging or logging.
- Does not guarantee cross-language compatibility; C#/.NET-specific format.
- Does not handle arbitrary object graphs with circular references; assumes acyclic data structures.
- Not a general-purpose persistence layer; optimized for in-memory serialization and IPC, not durable storage.
🪤Traps & gotchas
No .gitignore gotchas visible, but watch for: (1) Source Generator cache artifacts (obj/ and bin/) can cause stale code generation — always clean before major version changes. (2) opensourcesnk is committed; if modifying for production use, regenerate your own strong-name key and update Directory.Build.props <AssemblyOriginatorKeyFile>. (3) Benchmark payloads (JsonResponseModel.cs, NeuralNetworkLayerModel.cs) are hardcoded; modifying them breaks historical performance comparisons. (4) Incremental Source Generators require Visual Studio 2022.x or Rider 2022.x+; older IDEs will not trigger generation. (5) Unity support is 2021.3+; IL2CPP requires .NET Source Generator support, not available in older MonoVM Unity versions. (6) No explicit docker/container setup visible; local .NET 7 SDK installation is mandatory.
🏗️Architecture
💡Concepts to learn
- Zero-Encoding Serialization — MemoryPack's core innovation: instead of encoding data (VarInt, tags, string escaping), it copies C# memory layouts directly, enabling 10-200x speedups vs competitors.
- Incremental Source Generators — MemoryPack uses .NET 5+ Incremental Source Generators for compile-time code emission instead of IL.Emit runtime reflection, enabling native AOT and zero JIT overhead.
- IBufferWriter<T> and ReadOnlySequence<T> — Modern C# I/O abstractions that MemoryPack leverages for streaming serialization without allocating intermediate buffers; critical for high-throughput RPC.
- Native AOT Compatibility — MemoryPack's Source Generator-based code generation (no reflection, no IL.Emit) makes it compatible with .NET Native AOT, eliminating JIT cold startup penalty for microservices.
- IL2CPP Code Generation for Unity — MemoryPack emits serializers at compile time, avoiding C# reflection which is incompatible with Unity's IL2CPP ahead-of-time compiler used on iOS/consoles.
- Polymorphic Union Serialization — MemoryPack supports tagged unions (discriminated variants) for serializing inheritance hierarchies without type metadata overhead, critical for game networking and RPC polymorphism.
- Memory Layout Stability (struct padding awareness) — Zero-encoding copies raw struct memory; developer must be aware of C# struct layout (LayoutKind.Sequential) to avoid padding corruption across platforms.
🔗Related repos
neuecc/MessagePack-CSharp— Direct predecessor by the same author (neuecc); MemoryPack is the spiritual successor fixing MessagePack's encoding overhead via zero-encoding design.protobuf-net/protobuf-net— Primary performance competitor; MemoryPack benchmarks against it extensively to demonstrate 10x speed gains.dotnet/runtime— Provides System.Text.Json (one of the main comparison targets in benchmarks) and the Incremental Source Generator APIs that power MemoryPack's code generation.Cysharp/Utf8Json— Another serializer by Cysharp/neuecc; demonstrates the author's evolution from JSON (Utf8Json) → MessagePack → MemoryPack binary optimization.google/flatbuffers— Conceptual inspiration for zero-encoding design (README mentions 'similar to FlatBuffers'); FlatBuffers uses schemas, while MemoryPack works with POCO directly.
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive unit tests for MemoryPack serialization edge cases
The repo has extensive benchmark tests in sandbox/Benchmark but lacks dedicated unit test files for core serialization scenarios. With a 'zero encoding extreme performance' claim, edge cases like null handling, nested generics, circular references, and version tolerance (VersionTolerant.cs exists as benchmark but no unit tests) should have dedicated test coverage. This is critical for a serialization library where correctness is paramount.
- [ ] Create tests/MemoryPack.Tests.csproj alongside sandbox/Benchmark
- [ ] Add unit tests for null/default value handling across primitive and complex types
- [ ] Add tests for the version-tolerant serialization (referencing sandbox/Benchmark/Benchmarks/VersionTolerant.cs logic)
- [ ] Add tests for nested generic types and collection edge cases
- [ ] Integrate tests into .github/workflows/build-debug.yaml and build-release.yaml
Add Unity-specific integration tests and documentation
The package.json shows this is packaged for Unity (2022.3+), but there are no visible Unity-specific test scenarios or documented best practices. The sandbox has benchmark models but no Unity-specific serialization examples (e.g., MonoBehaviour serialization, struct alignment for Unity physics types). New contributors could add practical examples.
- [ ] Create docs/UNITY_INTEGRATION.md with serialization examples for common Unity types (Vector3, Quaternion, Transform hierarchies)
- [ ] Add sandbox/UnityTests directory with sample Unity scene data serialization patterns
- [ ] Document any platform-specific considerations (IL2CPP, WebGL, mobile memory constraints)
- [ ] Reference this in README.md's Unity section
Add performance regression detection to CI/CD pipeline
While sandbox/Benchmark contains extensive benchmarks (SerializeTest.cs, DeserializeTest.cs, Compression.cs), there's no automated regression detection in .github/workflows. For a library advertising 'extreme performance', tracking benchmark results across commits is critical. This prevents silent performance regressions from being merged.
- [ ] Add GitHub Action workflow (e.g., .github/workflows/benchmark-regression.yaml) using BenchmarkDotNet's result comparison
- [ ] Configure workflow to run sandbox/Benchmark/Benchmark.csproj on PRs and main branch
- [ ] Add result comparison logic (using tool like BenchmarkDotNet.Analysers or custom script) to comment on PRs with ±% changes
- [ ] Document baseline performance targets in CONTRIBUTING.md or docs/
🌿Good first issues
- Add TypeScript type-stubs code generation tests: The repo mentions TypeScript code generation (.ts files in root) and ASP.NET Core Formatter integration but sandbox/Benchmark lacks a benchmark/Benchmarks/TypeScriptCodeGenTest.cs to validate emitted TS correctness against serialized C# payloads.
- Document and test version-tolerant deserialization edge cases: README mentions 'Limited version-tolerant (fast/default) and full version-tolerant support' but sandbox/Benchmark/Benchmarks/VersionTolerant.cs likely needs more scenario coverage (added fields, removed fields, type evolution) with explicit test cases.
- Add struct array performance regression test: The README claims '50-200x faster for struct arrays' but sandbox/Benchmark only shows object benchmarks (SerializeTest, DeserializeTest). Create sandbox/Benchmark/Benchmarks/StructArrayBenchmark.cs comparing MemoryPack.Serialize<T[]> on large struct arrays vs competitors to lock in this claim.
⭐Top contributors
Click to expand
Top contributors
- @guitarrapc — 36 commits
- @hadashiA — 28 commits
- @neuecc — 17 commits
- @github-actions[bot] — 10 commits
- @alexyakunin — 2 commits
📝Recent commits
Click to expand
Recent commits
612a481— chore: add groups for dependabot (guitarrapc)e807380— Remove push-tag from build-release workflow (guitarrapc)59f48c2— Merge pull request #424 from Cysharp/ci/nuget_release (guitarrapc)e956744— ci: add id-token: write for NuGet Trusted Publish (guitarrapc)8997e81— Merge pull request #423 from Cysharp/feature/nuget (guitarrapc)3a5f7a6— chore: remove duplicate entry (guitarrapc)5806200— chore: Specify IsPackable=false on Directory.Build.props, explicitly true for target packages. (guitarrapc)0e82db3— ci: dependabot cooldown 65d2ae (guitarrapc)bbe6e75— Merge pull request #416 from Cysharp/ci/nuget_readme (guitarrapc)2d39bb9— ci: remove snupkg for SourceGenerator NuGet (guitarrapc)
🔒Security observations
MemoryPack demonstrates generally solid security posture for a serialization library. No critical vulnerabilities were identified in the static analysis. Main concerns are administrative: the presence of an .snk file that should be reviewed for key management practices, lack of explicit security documentation for a library that handles binary deserialization, and the need for clearer guidance on secure usage patterns. The codebase shows good practices with isolated benchmark code, use of GitHub Actions for CI/CD, and proper licensing. Recommended actions: (1) Review and secure the opensource.snk key file, (2) Create comprehensive security documentation, (3) Document deserialization security considerations and best practices for users.
- Low · Open Source SNK File Exposure —
opensource.snk. The repository contains an 'opensource.snk' file which is a strong name key file. While marked as 'opensource', this file should typically not be committed to public repositories as it can be used to sign assemblies. If this is a private key, it poses a signing key compromise risk. Fix: Review the contents of opensource.snk. If it contains a private key, remove it immediately and regenerate keys. Consider storing signing keys in secure key management systems rather than in source control. If this is intentionally public for open-source purposes, document this clearly. - Low · Benchmark Code May Contain Unsafe Patterns —
sandbox/Benchmark/Benchmarks/. The sandbox/Benchmark directory contains multiple benchmark files that test serialization performance. Benchmark code often uses unsafe operations or unvalidated inputs for performance testing. This code should not be part of production assemblies. Fix: Ensure benchmark code is properly isolated and not included in production NuGet packages. Verify that any unsafe code is clearly marked and documented. Consider code review of RawSerialize.cs and similar micro-benchmark files. - Low · No Explicit Security Policy or SECURITY.md —
Repository root. The repository does not appear to have a SECURITY.md file or security policy documented. For a serialization library that handles arbitrary binary data, having clear security guidelines and vulnerability reporting procedures is important. Fix: Create a SECURITY.md file documenting security considerations, known limitations, and responsible vulnerability disclosure procedures. Document any security best practices for users of the library. - Low · Lack of Input Validation Documentation —
README.md and documentation. As a binary serializer that deserializes untrusted data, MemoryPack should document security considerations around deserialization attacks (e.g., denial of service through deeply nested structures, circular references, or resource exhaustion). Fix: Add security considerations section to documentation covering: 1) Only deserialize data from trusted sources 2) Size limits and DoS protection 3) Any known limitations in handling malicious inputs 4) Best practices for secure integration.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.