SkillAgentSearch skills...

Bchan

A high-performance, lock-free bounded MPSC channel in Zig — 968 M msg/s (16p) · 150 M msg/s batched SPSC · one-click reproducible.

Install / Use

/learn @boonzy00/Bchan
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

bchan

CI License Zig Throughput

A high-performance, lock-free multi-producer single-consumer (MPSC) channel implementation in Zig, designed for low-latency concurrent messaging.

Features

  • Lock-free MPSC: Per-producer tail pointers eliminate contention
  • Zero-copy batch API: Reserve/commit for efficient bulk operations
  • Futex-based blocking: Energy-efficient waiting with exponential backoff
  • Dynamic producers: Safe registration and retirement with termination guarantees
  • SPSC/SPMC support: Unified API for different producer/consumer patterns
  • Production-ready: Comprehensive tests and benchmarks

Installation

Add to your build.zig.zon:

.{
    .name = "your-project",
    .version = "0.1.0",
    .dependencies = .{
        .bchan = .{
            .url = "https://github.com/boonzy00/bchan/archive/refs/tags/v0.2.0.tar.gz",
            .hash = "1220xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", // Run `zig fetch --save <url>` to get the actual hash
        },
    },
}

Then in build.zig:

const bchan = b.addModule("bchan", .{
    .source_file = .{ .path = "deps/bchan/src/lib.zig" },
});

Usage

Basic MPSC Channel

const std = @import("std");
const bchan = @import("bchan");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    // Create MPSC channel with 4 max producers
    const ch = try bchan.Channel(u64).init(allocator, 1024, .MPSC, 4);
    defer ch.deinit();

    // Register a producer
    const producer = try ch.registerProducer();
    defer ch.unregisterProducer(producer);

    // Send messages
    try std.testing.expect(producer.trySend(42));
    try std.testing.expect(producer.trySend(1337));

    // Receive messages
    const val1 = ch.tryReceive();
    const val2 = ch.tryReceive();

    std.debug.print("Received: {} {}\n", .{val1.?, val2.?});
}

Batch Operations

// Reserve space for batch
var ptrs: [64]?*u64 = undefined;
const reserved = producer.reserveBatch(&ptrs);
if (reserved > 0) {
    // Fill the batch
    for (0..reserved) |i| {
        if (ptrs[i]) |ptr| {
            ptr.* = i;
        }
    }
    // Commit atomically
    producer.commitBatch(reserved);
}

// Receive batch
var buf: [64]u64 = undefined;
const received = ch.tryReceiveBatch(&buf);

Blocking Operations

// Blocking send
producer.send(42);

// Blocking receive
const val = ch.receive();

Examples

See examples/simple.zig for a basic usage example, and benches/ for complete benchmark examples.

  • benches/batch.zig - High-throughput MPSC with batching
  • benches/spsc.zig - SPSC performance test
  • benches/mpsc_vyukov.zig - Vyukov MPMC comparison

Benchmarks

Run benchmarks with:

# Build optimized binaries
zig build -Doptimize=ReleaseFast

# Run MPSC benchmark 5 times with stats
./scripts/run_bench_mpsc.sh

# Run Vyukov comparison
./scripts/run_vyukov.sh

Benchmarks (AMD Ryzen 7 5700G • Zig 0.15.0 • ReleaseFast)

| Scenario | Producers | Throughput | Notes | |---------------------------|-----------|------------------|------------------------------------------| | MPSC (batched, zero-copy) | 16 | 968 M msg/s | Mean of 5 runs | | MPSC (batched, zero-copy) | 4 | 798 M msg/s | Mean of 5 runs | | SPSC (batched, zero-copy) | 1 | 150 M msg/s | Mean of 7 runs, σ ≈ 10 M msg/s, governor-locked | | SPSC (single-message) | 1 | 8–15 M msg/s | For comparison | | Vyukov MPMC (4p4c) | 4 | 19 M msg/s | Reference implementation |

Performance Comparison

bchan MPSC (16p, batched)      ██████████████████████████████ 968 M/s
bchan SPSC (batched, 1p1c)     ████████████████████ 150 M/s
bchan SPSC (single-msg)        ███████ 8–15 M/s
Vyukov MPMC                    ██ 19 M/s

All figures measured with CPU governor locked to performance and cores 0/1 isolated via cset shield. Reproducibility note: Batched SPSC throughput measured via scripts/run_peak_locked.sh (batch=64, 35 s duration, 7 repetitions). Individual run values ranged from 128–156 M msg/s; mean 150 M msg/s, σ ≈ 10 M msg/s. See scripts/run_peak_locked.sh (SPSC) and scripts/run_scaling_locked.sh (batch sweep) for one-click reproducible commands.

API Reference

Channel Creation

pub fn init(allocator: std.mem.Allocator, capacity: u64, mode: Mode, max_producers: u32) !Channel(T)
pub fn deinit(self: *Channel(T)) void

Producer Registration

pub fn registerProducer(self: *Channel(T)) !ProducerHandle
pub fn unregisterProducer(self: *Channel(T), handle: ProducerHandle) void

Send Operations

pub fn trySend(self: ProducerHandle, item: T) bool
pub fn send(self: ProducerHandle, item: T) void
pub fn trySendBatch(self: ProducerHandle, items: []const T) usize
pub fn sendBatch(self: ProducerHandle, items: []const T) usize

Batch Reserve/Commit

pub fn reserveBatch(self: ProducerHandle, ptrs: []?*T) usize
pub fn commitBatch(self: ProducerHandle, count: usize) void

Receive Operations

pub fn tryReceive(self: *Channel(T)) ?T
pub fn receive(self: *Channel(T)) T
pub fn tryReceiveBatch(self: *Channel(T), buffer: []T) usize
pub fn receiveBatch(self: *Channel(T), buffer: []T) usize

See bchan_algorithm.md for detailed algorithm documentation.

Documentation

Testing

Run the full test suite:

zig build test

Includes correctness tests for all modes, edge cases, and concurrent scenarios.

Contributing

Contributions welcome! Please see CONTRIBUTING.md for guidelines.

License

MIT License - see LICENSE file.

Changelog

See CHANGELOG.md for version history.

Related Projects

  • crossbeam-channel - Rust channels
  • moodycamel::ConcurrentQueue - C++ lock-free queues
  • zig-gamedev - Zig game development ecosystem
  • Experiment with backoff strategies, padding/alignment, and futex thresholds to tune performance.
  • Add CI jobs to run tests and (optionally) quick benches on supported runners. Add CI jobs to run tests and (optionally) quick benches on supported runners.
View on GitHub
GitHub Stars17
CategoryDevelopment
Updated4d ago
Forks2

Languages

Zig

Security Score

90/100

Audited on Mar 24, 2026

No findings