Cysharp/ZLinq
Zero allocation LINQ with LINQ to Span, LINQ to SIMD, and LINQ to Tree (FileSystem, JSON, GameObject, etc.) for all .NET platforms and Unity, Godot.
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 2w ago
- ✓13 active contributors
- ✓Distributed ownership (top contributor 43% 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/zlinq)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/zlinq on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: Cysharp/ZLinq
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/ZLinq 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 2w ago
- 13 active contributors
- Distributed ownership (top contributor 43% 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/ZLinq
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/Cysharp/ZLinq.
What it runs against: a local clone of Cysharp/ZLinq — 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/ZLinq | 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 ≤ 46 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of Cysharp/ZLinq. If you don't
# have one yet, run these first:
#
# git clone https://github.com/Cysharp/ZLinq.git
# cd ZLinq
#
# 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/ZLinq and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "Cysharp/ZLinq(\\.git)?\\b" \\
&& ok "origin remote is Cysharp/ZLinq" \\
|| miss "origin remote is not Cysharp/ZLinq (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 "Directory.Build.props" \\
&& ok "Directory.Build.props" \\
|| miss "missing critical file: Directory.Build.props"
test -f "ZLinq.slnx" \\
&& ok "ZLinq.slnx" \\
|| miss "missing critical file: ZLinq.slnx"
test -f ".github/workflows/benchmark.yaml" \\
&& ok ".github/workflows/benchmark.yaml" \\
|| miss "missing critical file: .github/workflows/benchmark.yaml"
test -f "README.md" \\
&& ok "README.md" \\
|| miss "missing critical file: README.md"
test -f ".github/copilot-instructions.md" \\
&& ok ".github/copilot-instructions.md" \\
|| miss "missing critical file: .github/copilot-instructions.md"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 46 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~16d)"
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/ZLinq"
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
ZLinq is a zero-allocation LINQ implementation for C# that replaces System.Linq with struct-based ValueEnumerables, eliminating heap allocations across method chains. It provides LINQ to Span (via C# 13's allows ref struct), LINQ to SIMD (automatic vectorization), and LINQ to Tree (for FileSystem, JSON, GameObject hierarchies), all while maintaining 99% compatibility with .NET 10's LINQ API and passing 9000 of dotnet/runtime's System.Linq.Tests suite. Monorepo structure: root ZLinq.slnx solution file; src/ contains core LINQ implementation using struct Enumerable types; sandbox/Benchmark/ contains BenchmarkDotNet suites with multiple config strategies (ColdStart, TargetFrameworks, SystemLinq comparison); tests/ runs System.Linq.Tests as drop-in validation; .github/workflows/ automates build and benchmark runs on release.
👥Who it's for
Game developers targeting Unity/Godot and high-performance .NET applications (netstandard2.0+, net8, net9) who need allocation-free collection operations; library authors implementing custom LINQ providers; and performance-conscious teams migrating from standard LINQ where GC pressure matters.
🌱Maturity & risk
Production-ready with strong signals: CI/CD pipelines in .github/workflows/ (build-debug.yaml, build-release.yaml, benchmark.yaml), comprehensive test coverage via System.Linq.Tests integration, published on NuGet, and actively maintained by Cysharp (author has prior shipping products: ZString, ZLogger, UniRx, R3). Verdict: actively developed and production-grade.
Low risk: single maintainer (Cysharp organization pattern) but strong track record; no heavy external dependencies visible (netstandard2.0 compatibility suggests minimal deps); source generators add complexity but are optional (drop-in replacment is opt-in via AsValueEnumerable()). Main risk is C# version constraints (requires C# 13 for full Span support via allows ref struct) which limits adoption on older codebases.
Active areas of work
Active benchmark validation via GitHub Actions (see .github/workflows/benchmark.yaml and benchmark_on_release.yaml); source generator development for drop-in replacement (Unity package config at sandbox/.editorconfig and package.json mention com.cysharp.zlinq.dropingenerator.internal); likely ongoing compatibility work for .NET 10 operators (Shuffle, RightJoin, LeftJoin, Sequence mentioned in README).
🚀Get running
Check README for instructions.
Daily commands:
# Run tests
dotnet test tests/System.Linq.Tests/System.Linq.Tests.csproj -c Release
# Run benchmarks (requires BenchmarkDotNet setup)
cd sandbox/Benchmark
dotnet run -c Release -f net8.0
# Build release package
dotnet pack src/ZLinq/ZLinq.csproj -c Release -o ./nupkg
🗺️Map of the codebase
Directory.Build.props— Central build configuration defining shared properties, target frameworks (netstandard2.0, 2.1, net8, net9), and version info for all projects in the solution.ZLinq.slnx— Solution file that orchestrates all projects; essential entry point for understanding the multi-platform project structure (Unity, Godot, .NET)..github/workflows/benchmark.yaml— Automated benchmark pipeline that validates zero-allocation claims across platforms; critical for understanding performance regression detection and CI/CD strategy.README.md— Primary documentation describing ZLinq's core value proposition (zero-allocation LINQ, SIMD, tree operations) and supported platforms..github/copilot-instructions.md— AI assistant guidelines for this repo, documenting architectural patterns and code style conventions contributors must follow.sandbox/Benchmark/BenchmarkDotNet/BenchmarkConfigs/BaseBenchmarkConfig.cs— Base configuration for all micro-benchmarks; essential for understanding how performance comparisons are structured and executed.CLAUDE.md— Repository-specific documentation for AI assistants; contains architectural notes and contribution guidelines.
🛠️How to make changes
Add a new zero-allocation LINQ operator
- Create the operator extension method in the core library with value-type enumerator pattern to avoid boxing (
(Source file location not in file list, but referenced in Directory.Build.props)) - Add a benchmark test comparing your operator to System.Linq equivalent (
sandbox/Benchmark/Benchmarks/LinqPerfBenchmarks.cs) - Verify allocation is zero by running benchmark with memory profiler (
.github/workflows/benchmark.yaml)
Add a new SIMD-accelerated operator
- Implement vectorized version of operator using System.Runtime.Intrinsics (
(Source file location not in file list)) - Create benchmark comparing scalar vs. SIMD performance (
sandbox/Benchmark/Benchmarks/SimdAggregate.cs) - Configure benchmark to run on systems with specific CPU capabilities (
sandbox/Benchmark/BenchmarkDotNet/BenchmarkConfigs/DefaultBenchmarkConfig.cs)
Add support for a new tree-like domain (e.g., new JSON parser)
- Implement IAsyncEnumerable or value-type enumerator for your domain type (
(Core library implementation, not in file list)) - Add usage benchmark demonstrating LINQ queries on your domain (
sandbox/Benchmark/Benchmarks/ReadMeBenchmark.cs) - Verify zero-allocation through benchmark profiling (
.github/workflows/benchmark.yaml)
Support a new target framework
- Add target framework identifier to Directory.Build.props PropertyGroup (
Directory.Build.props) - Update benchmark configuration to include new framework (
sandbox/Benchmark/BenchmarkDotNet/BenchmarkConfigs/TargetFrameworksBenchmarkConfig.cs) - Add framework-specific build job to CI workflow (
.github/workflows/build-debug.yaml)
🔧Why these technologies
- C# value types + generic constraints — Enables zero-allocation by using stack-based enumerators (struct) instead of boxed IEnumerator; compiler inlines method chains
- Span<T> and System.Runtime.Intrinsics — Provides both safe zero-copy LINQ on stack memory and SIMD vectorization for CPU-intensive operations
- BenchmarkDotNet — Isolates GC and JIT effects to accurately measure allocation and performance; critical for validating zero-allocation claim
- Multi-target frameworks (netstandard2.0 to net9) — Ensures LINQ operators work identically across .NET Framework 4.8 (via netstandard2.0), Unity 2022.3+, Godot, and modern .NET while using newer optimizations when available
- GitHub Actions CI with scheduled benchmarks — Detects performance regressions and allocation leaks automatically before release; benchmarks run on every commit and on schedule
⚖️Trade-offs already made
-
Value-type enumerators instead of IEnumerator interface
- Why: Eliminates boxing allocations and enables aggressive inlining by JIT, achieving zero-allocation chains
- Consequence: Generic constraints and extension methods become more verbose; IDE IntelliSense may be harder to navigate; cannot use traditional foreach on custom enumerators without special struct patterns
-
Struct-based design with explicit method chaining
- Why: Stack allocation of enumerator state; each chain builds on previous enumerator type without intermediate array allocations
- Consequence: Larger type signatures and method proliferation; potential for cache-unfriendly struct copies on larger enumerators (mitigated by JIT inlining)
-
Separate SIMD and scalar paths
- Why: Allows CPU-specific optimizations while maintaining fallback for older processors
- Consequence: Doubled maintenance burden; runtime feature detection adds small overhead; code duplication
-
Support netstandard2.0 alongside net8/net9
- Why: Covers .NET Framework 4.8 and legacy Unity/Godot versions while enabling forward-compatible optimizations
- Consequence: Cannot use newer language features (C# 12+) unconditionally; conditional compilation and API shims required
🚫Non-goals (don't propose these)
- Does not provide IAsyncEnumerable operators for async/await; async LINQ remains System.Linq.Async responsibility
- Does not implement deferred execution guarantees beyond method-chain semantics; once consumed, enumerator state is exhausted
- Not a drop-in replacement for System.Linq in all scenarios (e.g., reflection-based serializers may expect IEnumerable behavior)
- Does not optimize for single-pass enumeration beyond inlining; does not implement lazy stream fusion algorithms like Haskell GHC
🪤Traps & gotchas
C# version constraint: Full Span support requires C# 13 (allows ref struct); fallback for older versions exists but is limited. Benchmark sensitivity: BenchmarkDotNet results vary by CPU/OS; NuGetVersionsBenchmarkConfig and TargetFrameworksBenchmarkConfig in sandbox/Benchmark/ run different .NET versions—ensure you're testing against the right target. Unity/Godot integration: Package.json reference suggests Unity integration is under com.cysharp.zlinq.dropingenerator.internal; this is an internal package requiring separate setup. No visible package.lock or yarn.lock: netstandard2.0 target suggests minimal NuGet dependencies, but verify src/ZLinq/ZLinq.csproj for actual dependency list. Opensignkey: opensource.snk file present—signed assemblies may have version compatibility constraints.
🏗️Architecture
💡Concepts to learn
- ValueType Enumerables (Struct-based LINQ) — ZLinq's core mechanism—struct enumerables enable method chaining without heap allocations, unlike ref-class IEnumerable<T>; understanding this is essential to grasping why performance improvements exist
- C# 13
allows ref structmodifier — Enables LINQ to Span feature; without this, ref structs couldn't implement interfaces, blocking Span-based enumeration; critical for understanding the version constraints - SIMD (Single Instruction, Multiple Data) vectorization — ZLinq's 'LINQ to SIMD' feature automatically applies vector operations (System.Runtime.Intrinsics) to compatible LINQ chains; crucial for understanding performance claims on modern CPUs
- Source Generators (Roslyn) — ZLinq's optional drop-in replacement uses Roslyn source generators to rewrite System.Linq calls to ZLinq at compile-time; understanding this explains the
com.cysharp.zlinq.dropingenerator.internalpackage and opt-in acceleration - Tree-structured enumeration (Hierarchical LINQ) — ZLinq extends LINQ beyond flat sequences to tree structures (FileSystem, JSON, GameObject); this requires custom recursion strategies different from sequential LINQ operators
- Allocation profiling & GC pressure measurement — ZLinq's zero-allocation claim is validated via BenchmarkDotNet's memory allocation tracking; understanding how to read and interpret these benchmarks is essential for verifying performance improvements
- Generic constraint inference & type erasure — ZLinq achieves 99% LINQ compatibility while maintaining type safety across method chains; understanding how generic constraints and struct bounds work is key to modifying or extending operators
🔗Related repos
dotnet/runtime— ZLinq runs dotnet/runtime's System.Linq.Tests as its validation suite; this is the canonical LINQ implementation it claims 99% compatibility withCysharp/ZString— Sibling zero-allocation project by same author; uses similar struct-based builder patterns for string concatenation and shares design philosophyCysharp/ZLogger— Companion zero-allocation logger by Cysharp; often used alongside ZLinq in high-performance applications to eliminate GC pressure across the stackCysharp/SimdLinq— Predecessor to ZLinq's SIMD features; demonstrates vectorized LINQ operations that ZLinq builds upon and extendsneuecc/UniRx— Author's prior reactive LINQ implementation for Unity; influenced ZLinq's design for game engine integration and allocation-free operations
🪄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 benchmark suite for LINQ to Tree (FileSystem, JSON, GameObject)
The README prominently features 'LINQ to Tree' for FileSystem, JSON, and GameObject operations as a core feature, but the benchmark directory shows only traditional LINQ operation benchmarks (Distinct, Count, Cast, etc.). The FileSystem, JSON, and GameObject tree traversal implementations lack dedicated benchmarks to demonstrate their zero-allocation claims and performance advantages. This would validate a major selling point of the library.
- [ ] Create sandbox/Benchmark/Benchmarks/LinqToTree/ directory structure
- [ ] Add FileSystemTreeBenchmark.cs benchmarking directory traversal operations
- [ ] Add JsonTreeBenchmark.cs benchmarking JSON document traversal
- [ ] Add GameObjectTreeBenchmark.cs for Unity GameObject hierarchy traversal
- [ ] Compare allocation profiles against standard recursive/iterative approaches
- [ ] Integrate into existing BenchmarkDotNet configuration pipeline
Add LINQ to SIMD benchmark suite and validation tests
LINQ to SIMD is highlighted in the README and package description as a core feature, but there are no visible benchmarks in the sandbox/Benchmark/Benchmarks/ directory demonstrating SIMD operation performance or allocations. Similarly, the test coverage for SIMD operations appears incomplete. This gap makes it impossible for users to validate performance improvements from vectorized operations.
- [ ] Create sandbox/Benchmark/Benchmarks/LinqToSimd/ directory
- [ ] Add benchmarks for SIMD-optimized aggregations (Sum, Average, Min, Max)
- [ ] Add benchmarks for SIMD-optimized transformations (Select on vectors)
- [ ] Include CPU architecture variations (SSE, AVX, AVX2) in benchmark configs
- [ ] Create corresponding unit test file in test suite for SIMD correctness validation
- [ ] Document SIMD operation availability per target framework in CLAUDE.md
Add cross-platform target framework benchmark filter and CI validation
The repo targets netstandard2.0, 2.1, net8, and net9, plus Unity and Godot, but sandbox/Benchmark/BenchmarkDotNet/Filters/TargetFrameworkFilter.cs exists without corresponding comprehensive CI workflow validation. The benchmark.yaml and benchmark_on_release.yaml workflows should explicitly validate that zero-allocation properties hold across all target frameworks, especially given that SIMD and Span<T> availability differs significantly.
- [ ] Enhance .github/workflows/benchmark.yaml to explicitly test netstandard2.0, 2.1, net8, net9 separately
- [ ] Verify TargetFrameworkFilter.cs in sandbox/Benchmark/BenchmarkDotNet/Filters/ works correctly across all frameworks
- [ ] Add framework-specific allocation reporting to benchmark output (using memory diagnostic)
- [ ] Create matrix strategy in CI to catch framework-specific regressions
- [ ] Document known framework-specific limitations in CLAUDE.md (e.g., SIMD unavailable on netstandard2.0)
🌿Good first issues
- Add LINQ to Tree documentation and examples for Godot GameObject traversal: README mentions 'LINQ to Tree (FileSystem, JSON, GameObject)' but file list shows no example code for Godot; contributors could add example files to
sandbox/and update README with GameObject hierarchy LINQ patterns - Extend benchmark suite to cover LINQ to SIMD operations:
sandbox/Benchmark/BenchmarkDotNet/ExtensionMethods/hasConsumerExtensions.BinaryOperations.csandUnaryOperations.csbut no SIMD-specific benchmarks; contributors could add SIMD vectorization benchmarks to validate auto-SIMD feature claims - Add integration test suite for .NET 10 operators (Shuffle, RightJoin, LeftJoin, Sequence, InfiniteSequence): README lists these as newly supported but
tests/System.Linq.Tests/validation coverage is unclear; contributors could add specific test files for each .NET 10 operator totests/to ensure they pass the 9000-test suite
⭐Top contributors
Click to expand
Top contributors
- @neuecc — 43 commits
- @filzrev — 16 commits
- @guitarrapc — 10 commits
- @github-actions[bot] — 8 commits
- @dependabot[bot] — 6 commits
📝Recent commits
Click to expand
Recent commits
f1f95d3— Merge pull request #251 from Cysharp/dependabot/nuget/sandbox/ConsoleAppNetFramework48/nuget-8eaddb0034 (neuecc)01ec282— Bump the nuget group with 1 update (dependabot[bot])b84f0f9— chore(automate): Update package.json to 1.5.6 (github-actions[bot])f69303f— Merge pull request #249 from Cysharp/dependabot/github_actions/dependencies-8264a15060 (neuecc)2923daf— Merge pull request #250 from chikacc/main (neuecc)45b2b72— fix: resolve CS8170 and CS8347 compiler errors in Unity 6.5 (chikacc)71614a9— chore(deps): bump actions/upload-artifact in the dependencies group (dependabot[bot])7da0ef2— Merge pull request #248 from filzrev/chore-update-systemlinq-compatibility-tests-4 (neuecc)37eb0c0— chore: update system.linq compatibility tests to .net 11 preview.2 (filzrev)7aea0cf— chore: add groups for dependabot (guitarrapc)
🔒Security observations
The ZLinq repository demonstrates a strong security posture overall. It is a well-maintained open-source .NET library with proper CI/CD workflows, dependency management via Dependabot, and no obvious injection vulnerabilities detected in the file structure. The project uses legitimate code signing practices with an opensource.snk file. No hardcoded secrets, credentials, or dangerous patterns (SQL injection, XSS) were identified in the provided documentation and file structure. Minor recommendations include ensuring strong name key file permissions are properly restricted and maintaining regular dependency updates through Dependabot. The project follows standard security practices for open-source .NET libraries.
- Low · Unsigned Assembly with Public Key File —
opensource.snk. The repository contains an 'opensource.snk' file which is a public key file used for signing assemblies. While this is common for open-source projects, the presence of a strong name key file in the repository could theoretically be misused if the private key is compromised or if the file permissions are not properly restricted. Fix: Ensure that the strong name key file has restricted file permissions and is not committed to version control if it contains sensitive information. Consider using a secure key management system for production assemblies. - Low · Dependency Management Configuration Present —
.github/dependabot.yaml, Directory.Build.props. The repository contains a 'dependabot.yaml' configuration file and 'Directory.Build.props' which manages dependencies. While dependency management is good practice, ensuring all dependencies are regularly updated and scanned for vulnerabilities is critical. Fix: Ensure Dependabot is configured to automatically scan dependencies, create pull requests for updates, and that security advisories are reviewed regularly. Monitor NuGet package vulnerabilities through official channels. - Low · Benchmark Project with External Tool Dependency —
sandbox/Benchmark/. The repository includes a benchmark project that uses BenchmarkDotNet and appears to test various LINQ implementations. Benchmark projects may pull in numerous dependencies that require security validation. Fix: Regularly audit and update benchmark dependencies. Ensure that benchmark configurations do not disable security features or validation mechanisms.
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.