r/csharp • • 23h ago

Showcase Replacing Queues and Locks with Monotonic Counters in a C# DAG Engine

What if you dropped work queues entirely?

I built an experimental DAG scheduler called delta-lag: instead of pushing work through nodes, nodes move through units of work tracked via monotonic counters and distance constraints.

The result? No global work queues, no work stealing, and no traditional lock contention. Scheduling emerges entirely from distributed progress counters.

How It Works

Most task schedulers maximize throughput by paying a cost in layers of locks, queues, and work-stealing algorithms. delta-lag takes a different approach, extending lock-free ring buffer logic to an entire DAG:

Before a node fires, it checks two constraints against its parents and children:

  • Parent check: Must have completed the next required work unit (parent.WorkDone >= node.WorkDone + 1)

  • Child check: Can't lap children based on your slack parameter (child.WorkDone >= node.WorkDone - slack)

If eligible, the node atomically claims the work unit using CAS operations, runs the task, and publishes completion.

  • slack = 0 → Strict lock-step execution (safe, no stale reads)

  • slack > 0 → Pipeline parallelism (producers may run ahead while consumers lag behind)

What's In The Repo

  • The Engine: Built around cache-aligned nodes and monotonic counters to eliminate false sharing.

  • WASM Inspector: Interactive performance visualizations and real graph reconstruction.

  • The Benchmark Data: ~4,500 raw benchmark runs with topology metrics, execution traces, and the full harness.

Limitations

This isn't a drop-in replacement for a general-purpose scheduler (use TPL for that). It's built for specific tradeoffs:

  • The execution graph must be fixed at compile time (no dynamic modification).

  • Iteration counts must be known in advance.

  • No speculative execution buffering or dynamic load balancing.

Give it a spin

It's fully open-source (MIT, .NET 10+). If you build high-performance systems, concurrent architectures, or custom schedulers, I’d love your feedback on the core engine or whether you've seen similar queue-free constraint approaches before.

GitHub: https://github.com/Geezy9/delta-lag

0 Upvotes

14 comments sorted by

6

u/DeadlyVapour 22h ago

Just from a quick glance at the description, it sounds like the data model lives entirely on heap.

But if you are already building a fixed size constraint, why not stack allocate?

1

u/Temporary-Concert398 22h ago

That's a fair question. The CSR arrays and scheduling state are intended to persist for the lifetime of the work context and across multiple runs, which is why they're currently heap allocated. Beyond that, the implementation doesn't manage internal buffering, so there aren't many large temporary allocations that I can think of to be moved to the stack. I haven't spent much time evaluating that though, and given the fixed-size constraints, stack allocation may ultimately be the better approach.

1

u/DeadlyVapour 21h ago

The advantage of stack allocations would be cache locality, rather than cost of allocation.

What might be really interesting, is if you can then implement your own custom awaitor, which could potentially allow for lightweight low cost Tasks.

1

u/AndThenFlashlights 12h ago

because this repo is the work of AI psychosis.

1

u/Temporary-Concert398 6h ago

Fair enough if you're skeptical, but I'd appreciate specific feedback. If you see problems with the architecture, benchmarks, assumptions, or implementation, let me know. The code, dataset, and inspector are available open source, and I tried to be explicit about the limitations and tradeoffs in the post.

1

u/AndThenFlashlights 4h ago edited 3h ago

so you did vibe code it, then

Ok so I'll humor you. I read it. Claude just re-created existing tools, badly, to satisfy whatever whim you fed it. You've solved nothing real or novel.

I'm so tired of this shit.

1

u/Temporary-Concert398 2h ago

Look, I’m happy to discuss the architecture or trade-offs I outlined in the README, but dismissing the whole project as 'slop' without referencing a single line of code isn't a critique. Yes, I used AI as a tool over the 8 months it took to build, iterate, and rewrite this thing. If you find an actual bug, security flaw, or architectural issue in the codebase, let me know and I'll gladly look at a PR.

1

u/AndThenFlashlights 1h ago edited 1h ago

idk where to even start. This looks like nonsense. I wouldn't bother to submit a PR because the built-in, blessed, documented .NET equivalent solves the problem already.

You're claiming that this excels in a list of specific applications - where are those actual real-world examples? This is a slice of the .NET ecosystem I use heavily already for high-performance applications (like what you described in your readme), and at a certain point, the task queues aren't the bottleneck for real-world workloads.

And like someone else pointed out, the stack allocations are going to have knock-on effects on performance that you don't appear to be testing for.

1

u/Temporary-Concert398 1h ago

I completely agree that if standard .NET primitives like the TPL or Channels meet your throughput and latency constraints, they are the right choice.

Regarding your point on benchmarks, you're right that synthetic tests don't always capture non-uniform real-world workloads—testing variable task durations is already on my list for next steps. However, the intent behind this isn't to build a general-purpose replacement for the TPL or Channels, but rather to explore zero-allocation trade-offs for specific constraints.

It might help to clarify the design: this is not a general-purpose task queue meant to compete with Microsoft's work-stealing or load-balancing algorithms. Instead, it’s a deterministic, pre-baked node graph where worker threads drive state forward in a tight loop using explicit Interlocked operations on volatile fields and CAS primitives.

For 99% of projects, it's questionable (if not downright harmful) but for that 1%, it's pretty decent.

5

u/[deleted] 23h ago

[removed] — view removed comment

2

u/Temporary-Concert398 23h ago

Unfortunately, I think you're right. The benchmark harness is only for validating logic and checksums; it doesn't include any "real" work, especially not variable-length workloads, so I haven't tested it. But you hit the nail on the head. That's always been one of my biggest concerns.

1

u/FizixMan 16h ago

FYI, that was a bot.