Ant Farm - A concurrent M:N jobs distributor
Nathan Riddick
nathan.judge at gmail.com
Sat Oct 10 20:50:12 UTC 2026
On Sunday, 30 August 2026 at 21:21:46 UTC, Nathan Riddick wrote:
> On Sunday, 30 August 2026 at 21:11:01 UTC, Sebastiaan Koppe
> wrote:
>> On Monday, 24 August 2026 at 23:04:33 UTC, Nathan Riddick
>> wrote:
>>> [...]
>>> https://github.com/nriddick/antfarm
>>
>> This is amazing work, thank you.
>>
>> Do you have any plans for things on top?
>
> I'm working on an actor model with managed lifetimes, where
> dispatch onto the ant farm is an exclusive borrow and the actor
> can mutate external (non-buffer) state through its handle. The
> WIP is in the main branch.
My psychosis has progressed. My idea of an "actor" system bolted
onto the ring transport was barely nascent before, and now it
comes in two flavors: "Public" identities with inboxes and
copyable handles. And "private" actors where root actors are
parked with no external owner and narrow external access in the
form of requesting a cancellation, and children have one
exclusive parent. All kinds can be dispatched in generationed
"waves", where the wave is a fence guaranteeing for example that
participants can safely view and edit their exclusively borrowed
private state and publish a public-safe projection for the next
generation. Plus assorted usability features and bug fixes.
I also went from synthetic ~300 million Payloads per second on
the Ryzen 5500 to ~1.7 billion. That's single delivery of 1-word
payloads w/ associated function pointer callback, concurrently
from 4 producers to 8 consumers (6 cores 12 threads). And big
batches, typical synthetic throughput caveats etc. The biggest
gains were compacting/eliding per-Payload headers when tables
have more uniform composition, often chopping 128 byte headers
down to 8 or even 0. Actors can range from tens to hundreds of
millions dispatched per second depending on your lifetime,
allocation and execution strategies. Huge pages after these
optimizations now don't do much good, where before they could net
~50% extra throughput.
https://github.com/nriddick/antfarm/blob/main/PERFORMANCE.md
Conway's Game of Life, one actor per cell
https://github.com/nriddick/antfarm/tree/main/examples/life
`examples/life` is a toroidal board where every cell is a private
child actor. The cell callback reads its eight wrapped neighbours
from the current projection and writes only its own slot in the
next one. One actor per cell is deliberately "1:1" rather than
targeting step speed:
```d
output[index] = cast(ubyte) (neighbours == 3 || (input[index] &&
neighbours == 2));
```
The root owns the cohort and runs one wave per generation:
```d
if (run.cells !is null) // resumed: the
previous wave joined
{
if (context.cancelled || run.cells.outcome(context).cancelled)
return PrivateRootDisposition.finish; // discard a
partial wave
run.board.current = 1 - run.board.current; // swap
projections
++run.board.generation;
--run.remaining;
}
if (context.cancelled || run.remaining == 0)
return PrivateRootDisposition.finish;
// first time through: createChildren!Cell(w * h), spawn one per
cell
run.cells.start!stepCell(context);
return PrivateRootDisposition.waitChildren;
```
The calling application owns the two buffers, and there are no
extra fences. Ordering chain goes like this, also see
`docs/design`:
1. Cell callback writes.
2. Shard completion join.
3. Wave credits.
4. Root resumes from `waitChildren`.
5. Next wave is published.
6. Next wave's reads.
256×256 board, 200 generations per request, including cohort
creation and collection:
| Workers | Generations/s | Cell updates/s |
| ---: | ---: | ---: |
| 0 (inline) | 1,631 | 107M |
| 2 | 2,707 | 177M |
| 6 | 4,079 | 267M |
65,536 actors stepping in joined waves now rival what the raw
transport layer could do last time in updates per second.
Also builds to termbox2 TUI app. It has pause, single-step,
randomize, a glider stamp, cursor editing, and speed control:
```text
make -C examples life
examples/.build/life 2 # 2 workers; 0 runs on the UI thread
```
Anyways, hope someone else finds my delirious ravings useful. I
have a 16c/32t AMD 5900XT on the way to replace the 6x/12t 5500
and probe higher thread counts / multi CCX.
More information about the Digitalmars-d
mailing list