Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/znippy-zoomies

.nornir/gatling-for-idiots.md

Gatling for idiots — the 1 → N → 1 idea in plain words

Class: idiot. No jargon, nothing assumed.

The story of why Gatling and which one to call. The proper design is in gatling-design.md; the how-to with signatures is gatling-guide.md; the real bug this is all based on is written up with the osm work in the sibling repos (znippy / znippy-osmfeed .nornir/osm-katana-gatling-vs-rayon.md).

The picture

Your computer has lots of cores — little workers that can each do a job at the same time. You want them all busy. If only 1 is busy and the rest sit idle, you're using a few percent of the machine and everything crawls.

Think of a kitchen:

   1 waiter   →   N cooks   →   1 plater
  brings the      each cooks     puts finished
  raw food        a full dish    dishes on the
  (does NOT        start to       pass, in order
  cook anything)   finish, never  (does NOT cook
                   waiting for     anything)
                   the others

If all the cooking happens in the cooks, the kitchen flies. The disaster is making the waiter or the plater cook — there's only one of each, so one person does all the hard work while everyone else stands around. That's the bug that once dropped osm-katana from "all 32 cores" to "~3 cores": we'd made the ends cook (read the whole 8 GB then sort it one-at-a-time, walked the whole file to find boundaries, assembled the final result at the pass). Funny twist — while broken, the old rayon way looked faster, and people almost blamed Gatling. Gatling was fine; we'd just told the waiter to cook. We moved all the cooking back into the cooks and it went back to a flat 100% on all cores, even on the entire planet's map (10.58 billion points).

The one thing to remember: the waiter and the plater never cook. All the hard work — finding boundaries, decoding, sorting, parsing, encoding — happens in the cooks in the middle, with nobody waiting on anybody.

Which one do I call?

There's one idea (1 → N → 1) in a few shapes. Pick by your situation:

Do you already have all the work in hand (a list, an array, a grid)? Or is it streaming in (bytes off a file/socket)?

I already have the list → fork-join (gatling_forkjoin)

It's streaming in → the streaming engine (gatling)

It's network / disk I/O, not CPU → the async sibling (gatling::io)

Uploading a pile of files to S3, doing many network calls, lots of fsyncs? Those cooks aren't cooking, they're standing at the phone waiting for someone to pick up. Threads would just block. Use gatling::io::run (results as they land) or gatling::io::run_ordered (results in order). It keeps a fixed number of calls "in flight" and starts the next the instant one finishes.

The two rules

  1. The ends never cook. Reader reads, plater stitches-in-order, all heavy work is in the cooks.
  2. Never use rayon. It's banned in this codebase — its hidden shared pool is exactly what bit osm-katana. Gatling is the replacement everywhere.

How to tell if you broke it

Watch your cores while it runs (htop, btop, whatever). One core pegged and the rest asleep = you made an end cook, or you wrote a plain for loop. All cores busy = you did it right. If everything's busy at the start but it sags to one core at the end, you've got one monster job — switch to gatling_for_each_balanced and give it a weight.