The World Vol 9 · The Village
ch 98 / 105
Chapter 98

Whose Turn to Think

A plan that takes thirty-six ticks

Every model call in this volume so far was made by hand. A bench picked a villager, picked a tick, ran the world to that boundary, asked, and judged the answer when it came back. Eight chapters of villagers thinking, and not one of them decided whose turn it was. The daemon has to, and the arithmetic it has to decide under is the arithmetic chapter 90 put beside the tick: a plan on the small model came back in 328 milliseconds when it stopped at 14 tokens, and the plans this volume has been asking for since, with a schema on the request and a situation to embed first, come back in three to four seconds. At ten ticks a second that is thirty to forty ticks a plan, and a tick is a hundred milliseconds that nothing inside it may spend on a socket.

Three people and one worker asking one question at a time is a round of about a hundred and ten ticks if every plan takes thirty-six. Twenty-four people is nine hundred. The village this volume runs is three, and the reason the number is in the file rather than the code is that the arithmetic is meant to bite at any size: what decides whether a village can think is not how many people are in it but how many ticks pass between one villager's turns, and that number has a cap on it already, because the sixth check refuses a proposal older than two hundred ticks. A scheduler that lets a villager's turn come round every three hundred ticks is a scheduler buying answers the seam throws away. The scheduler wakes outside the tick, on a cadence in ticks, with one worker, and it never makes a tick wait.

So the thing this chapter builds is small and its rules are few. It wakes on a plain count of ticks, at the daemon's own loop boundary, which volume 7 named as the one place where no phase is part way through, no view is open and no creature is half stepped, and which volume 8 hung its embedding job on. It orders the villagers by a score a reader can add up, hands the first of them to a worker with a send that gives up if the worker is busy, and returns. The worker calls the models; the answer comes back whenever it comes back; the boundary that finds it runs the six checks over the world as it stands at that boundary, and an accepted step goes into the villager's one-slot mailbox, values and not pointers, replacing what is there. The tick side takes it or does not.

Every decision a villager makes is a decision about a world that has already moved on, and the sixth check is what makes that safe. That sentence is the design and not a defect of it: a question asked at tick 2400 is answered at tick 2437, and the reading the checks are handed is 2437's, so a plan whose premises have gone is refused and the habit has the ticks. Three things the scheduler refuses fall out of the same arithmetic, and each is run below. A villager already with a worker is not queued again. A request that has waited in the queue past the staleness cap is dropped without a call, because a decision about a world that is gone is worse than no decision and costs the same. And a village cannot be accelerated: when the world is run faster than a call can land inside the cap, the scheduler says so on its own line and stops asking, and every villager runs the utility rule from there.

A hundred and forty-three conversations the memory allows

The worker count is computed before it is chosen, and the computation is volume 8's. A model held at a context costs three sums: the weights, one key-and-value cache a conversation in flight, and what the server keeps beside them, which was weighed against this server at this context and committed. What is left of the ceiling divided by one cache is how many further conversations fit, and lang.Plan.More is that division.

▣ Build · stage 1 — the budget, worked from the three sums at 4,096 tokens
$ go run ./cmd/turns -mode budget
turns: how many workers the budget allows, worked from volume 8's three sums

  the ceiling        8,000,000,000 bytes
  the context        4096 tokens, off configs/models.json
  a cache number     2 bytes

  model             weights        one cache         overhead        all three   a cache more
  small         397,807,936       50,331,648      320,032,704      768,172,288     50,331,648
  hero        4,683,073,952      234,881,024      163,753,568    5,081,708,544    234,881,024

  the small model resident alone, one conversation in flight
    what it costs                                 768,172,288
    left over                                   7,231,827,712
    further conversations that fit                        143
    so the memory allows 144 workers on the small model, if memory were the only thing
  both resident, one conversation of each in flight, which this server never does
    what it costs                               5,849,880,832
    left over                                   2,150,119,168
    further small conversations that fit                   42

  and the number the arithmetic has no term for: the server holds ONE model resident at
  a time, so a second worker asking for the embedding model while the first is on the
  small model evicts the small model and pays its load again when the first comes back
  to it. Memory allows many; residency allows one model; whether a second worker buys
  anything at all is not in this arithmetic and is measured by -mode live -workers 2
  the file says 1 worker(s), and the measurement is what the file was set from

The small model resident alone costs 768,172,288 bytes of an eight-thousand-million ceiling, and every further conversation of it is one more cache of 50,331,648: a hundred and forty-three of them fit in what is left. Even with the hero model resident beside it, which this server never allows, forty-two would. Memory is not the constraint and the arithmetic says so in one division. What the arithmetic has no term for is the rule volume 8's contract runs the server under, OLLAMA_MAX_LOADED_MODELS=1: one model in memory, and a call on any other evicts it. A plan is an embedding and then a generation, on two different models, so one worker changes the resident model twice a plan whatever the count; a second worker asking for the embedding model while the first is generating evicts the small model under the first and makes it load again, and the load is paid on the way in and on the way back. The count that memory allows is not the count residency allows, and the file says one. Whether a second one buys anything is measured below, in the worked failure, with the result reported whichever way it went.

The other number the cadence is set against is the round trip. A wake every fifty ticks is five seconds at the watched pace, and a plan lands in three to four, so the worker is free again at nearly every wake and the queue is handed one request a wake. A reflection is dearer: chapter 94 grouped its calls by model into three changes of resident and measured 7.476 seconds for one, which is seventy-five ticks, so a wake falls while it is in flight and hands nothing, and the villager behind it waits a hundred ticks for a turn instead of fifty. Three reflections owed at once, which is what a village founded on one tick owes every two thousand ticks of its life, are two hundred and forty ticks of worker, and the third in line is dropped unasked before it is reached. The recording below has that happen twice.

∑ Math Interlude — the round, the cadence, the cap and the score, in ticks

Every number here is in ticks, at ten ticks a second, because that is the pace every figure on this page was taken at; the same seconds in a world run a hundred times faster are a hundred times more ticks, and the last section runs that.

The budget first. What is left of the ceiling with the small model resident is 8,000,000,000 minus 768,172,288, which is 7,231,827,712. One more conversation is one more cache, 50,331,648 bytes. Divide and drop the remainder: 143. That is More, and it is the number of workers the memory would allow beyond the first; residency allows one model, so the count is one.

The round next. One plan is a call of about 3.6 seconds, which is 36 ticks. Three villagers served one at a time is 3 × 36 = 108 ticks a round if the worker is never idle. The cadence is 50, so with one request handed a wake the round is really 3 × 50 = 150 ticks, and each villager's plan, which runs 60 ticks and then runs out, leaves it on the habit for about 90 of every 150. The cap is 200: a request queued at a wake and still not handed four wakes later has waited 200 ticks, and at the fifth it is 250, which is over the cap and dropped. A reflection is about 80 ticks, so two reflections ahead of a third request are 160 ticks of waiting before the third's own wake comes, and the recording shows the third dropped at 250.

The score last. A villager's place at a wake is the sum of three terms turned into ticks: how long its plan has been run out for; twenty ticks for every memory laid down for it since its last answer; and four hundred ticks if a person has come into its sight since. At wake 15 in the recording, Ander's plan had been out for 5 ticks, one memory had been laid down, and a stranger was in sight: 5 + 20 + 400 = 425. Halla's reflection had been waiting 153 ticks with four memories: 153 + 80 = 233. Mose: 121 + 0 = 121. Ander first, and the tie that never came would have gone to the lower identity.

more = (ceiling − small) ÷ cache, remainder dropped

score = stale + E × events + F × faced, best first, ties by identity

dropped when now − queued > cap; stopped when landed − asked > cap

ceiling, small, cachebytes: 8,000,000,000; the small model's three sums at 4,096 tokens, 768,172,288; one conversation's cache, 50,331,648
morefurther conversations that fit; 143
staleticks since the villager's plan ran out, or since it was enrolled; nought while a plan is running
eventsmemories laid down for it since its last answer landed
faced1 if a person came into its sight since its last answer and is still there, else 0
E, Fthe two weights in configs/thought.json, in ticks; 20 and 400
capthe seam's staleness cap, in ticks; 200
queued, asked, landedthe tick a request entered the queue, the tick it was handed to a worker, the boundary tick its answer was taken at
a ÷ b, a × ba divided by b; a multiplied by b

A wake every fifty ticks

The scheduler is a new file in the village package, and the package's rule holds: it imports the coordinate package and the configs and nothing else, opens no connection, calls no model, reads no clock and draws no number. What it knows about the world it is told at the boundary, as counts and flags; what it hands a worker is a value; what comes back crosses a channel as a value. Its settings are a fifth block in the file the retrieval, reflection, planning and seam blocks already share.

▣ Build · stage 2 — the scheduler block, and the type that reads it
// configs/thought.json — extend: a fifth block after seam
  "scheduler": {
    "every": 50,
    "event": 20,
    "faced": 400,
    "workers": 1
  }
// internal/village/schedule.go — create
package village

// Scheduling is the block of configs/thought.json the scheduler runs
// by: the cadence, in ticks; what one memory laid down since a villager
// last thought is worth against its staleness, in ticks; what a person
// standing in front of it is worth, in ticks; and how many workers ask
// on its behalf.
type Scheduling struct {
	Every   int `json:"every"`
	Event   int `json:"event"`
	Faced   int `json:"faced"`
	Workers int `json:"workers"`
}

// Job is what a request is for. A plan is one embedding and one
// generation; a reflection is chapter 94's cycle, a generation, then
// the questions embedded, then a generation a question, then every
// accepted thought embedded; a line is one generation on the hero
// model, which is the only request that changes which model is
// resident twice on its own.
type Job string

const (
	PlanJob    Job = "plan"
	ReflectJob Job = "reflection"
	LineJob    Job = "line"
)

// Priority is the three terms a villager is ordered by at a wake and
// the score they come to. Stale is how many ticks its plan has been
// ...
type Priority struct {
	Stale  int
	Events int
	Faced  bool
	Score  int
}

// Request is one turn to think, as the scheduler hands it to a worker:
// whose, what for, the tick it was queued at, the tick it was handed
// at, the priority it was ordered by, and what the worker needs to
// know about the world at the tick it was handed, taken at that
// boundary and carried as values. A worker reads a Request and never
// the roster.
type Request struct {
	Who      sim.EntityID
	Name     string
	Job      Job
	Queued   int
	Asked    int
	Priority Priority
	Ask      Asking
}

Two ticks on a request and not one, and the difference is the second refusal. Queued is when the villager entered the queue and Asked is when a worker was handed it; the prompt is rendered from the world at Asked, and the sixth check ages a proposal from it, but the queue ages a request from Queued, because a villager that has been waiting for its turn since a wake four cadences ago is a villager whose reasons for the turn are gone. Asking is the world as the worker gets it: the persona, the cell and home, who the eyes returned at this boundary, the villager's rows, and a fresh copy of the vectors. Every field is a value; the worker never holds a pointer into the roster, for the reason chapter 91 gave for the mailbox.

▣ Build · stage 3 — the score, and an order that is total
// internal/village/schedule.go — add
// Priority is the three terms for one villager at tick now.
func (s *Scheduler) Priority(id sim.EntityID, now int) Priority {
	st := s.st[id]
	p := Priority{Events: st.events, Faced: st.facing && st.facedAt > st.landed}
	if now > st.until {
		p.Stale = now - st.until
	}
	p.Score = p.Stale + s.Event*p.Events
	if p.Faced {
		p.Score += s.Faced
	}
	return p
}

// rank sorts requests best first: a line owed to a person ahead of
// everything, then by score, highest first, and on a tie by identity,
// lowest first, so that the order is total and two wakes over the
// same facts are the same wake.
func (s *Scheduler) rank(now int) {
	for i := range s.pending {
		r := &s.pending[i]
		r.Priority = s.Priority(r.Who, now)
		if r.Job == PlanJob && s.st[r.Who].owed {
			r.Job = ReflectJob
		}
	}
	sort.SliceStable(s.pending, func(i, j int) bool {
		a, b := s.pending[i], s.pending[j]
		if (a.Job == LineJob) != (b.Job == LineJob) {
			return a.Job == LineJob
		}
		if a.Priority.Score != b.Priority.Score {
			return a.Priority.Score > b.Priority.Score
		}
		return a.Who < b.Who
	})
}

The faced term is the one that had to be measured before it was right. The first draft scored a person in sight as four hundred ticks at every wake for as long as the person stood there, and in the first live run of it Halla, who could see the stranger from across the valley, was handed every turn from tick 3200 to the end while Mose's plan waited 313 ticks and Ander's 256. A term that never clears hands one villager the worker. What the term means now is a reason to think once: it is on from the tick a person came into sight until the villager's next answer lands, and off after that until the person leaves and comes back. The test below holds that, and the tie-break is the last line of the sort: two villagers at the same score are placed by identity, lowest first, so the order is a function of the facts and the queue at every wake replays.

▣ Build · stage 4 — the wake: drop, queue, rank, hand off with a send that gives up, return
// internal/village/schedule.go — add
// Wake runs one wake at the boundary of tick now, and hands off. It
// does four things, in this order, and then returns whatever the
// workers are doing.
// ...
func (s *Scheduler) Wake(now int, prepare func(Request) Request) Wake {
	w := Wake{Tick: now}
	s.Wakes++

	kept := s.pending[:0]
	for _, r := range s.pending {
		if now-r.Queued > s.Stale {
			s.Dropped++
			w.Dropped = append(w.Dropped, r)
			continue
		}
		kept = append(kept, r)
	}
	s.pending = kept

	// A stopped scheduler queues nobody and hands nothing; the wake
	// ranks the villagers as it would have, so a bench can print what
	// the order would be, and says why nothing is done about it.
	if s.Stopped != "" {
		// ...
		w.Said = "stopped: " + s.Stopped
		return w
	}

	queued := map[sim.EntityID]bool{}
	for _, r := range s.pending {
		queued[r.Who] = true
	}
	for _, id := range s.people {
		st := s.st[id]
		if st.waiting || queued[id] {
			continue
		}
		job := PlanJob
		if st.owed {
			job = ReflectJob
		}
		s.pending = append(s.pending, Request{Who: id, Name: st.name, Job: job, Queued: now})
	}
	s.rank(now)

	handed := 0
	offering := true
	kept = s.pending[:0]
	for _, r := range s.pending {
		if offering && s.busy < s.Workers && !s.st[r.Who].waiting {
			r.Asked = now
			if prepare != nil {
				r = prepare(r)
			}
			select {
			case s.Inbox <- r:
				s.busy++
				s.Handed++
				handed++
				s.st[r.Who].waiting = true
				w.Handed = append(w.Handed, r)
				// ...
				continue
			default:
				offering = false
			}
		}
		kept = append(kept, r)
		// ...
	}
	s.pending = kept
	// ...
	return w
}

Read the four parts in order, because the order is the whole of the first two refusals. Requests that have waited past the cap are dropped before anything else, unasked, and counted. Every villager that is neither in the queue nor with a worker is queued, so a villager with a worker is skipped here and stays skipped until its answer lands. The queue is ranked by the terms as they stand now, so a villager's place moves with what has happened to it since the last wake, not with when it entered. And the head is handed off with a select whose default is to keep the request queued: Inbox is one slot a worker, a put into an empty slot succeeds at once, and a put into a full one is not made. Nothing in this function can wait, and the loop that calls it between two ticks is the loop that runs the ticks.

▣ Build · stage 5 — the answers taken at the boundary, and the third refusal
// internal/village/schedule.go — add
// Take drains the landings channel with receives that give up, hands
// back every answer that has arrived and is due at this boundary, and
// keeps the rest for a later one. For each taken it records the
// ...
func (s *Scheduler) Take(now int, held []Landing) (taken, kept []Landing) {
	for {
		select {
		case l := <-s.Landings:
			held = append(held, l)
			continue
		default:
		}
		break
	}
	for _, l := range held {
		if l.LandAt > now {
			kept = append(kept, l)
			continue
		}
		taken = append(taken, l)
		s.busy--
		s.Landed++
		st := s.st[l.Request.Who]
		st.waiting = false
		st.landed = now
		st.until = now
		st.events = 0
		if l.Request.Job == ReflectJob {
			st.owed = false
		}
		if trip := now - l.Request.Asked; trip > s.Stale {
			s.Late++
			if s.Stopped == "" {
				s.Stopped = fmt.Sprintf("at tick %d an answer asked for at tick %d landed %d ticks later, and the cap is %d: at this pace no answer can land in time, so the village runs the utility rule from here",
					now, l.Request.Asked, trip, s.Stale)
				s.pending = nil
			}
		}
	}
	return taken, kept
}

The third refusal is one comparison at the landing. An answer that took longer to come back than the cap is an answer the sixth check refuses on arrival, and a scheduler that has watched one do so knows what every later call at this pace would do, so it writes down why and stops: the queue is emptied, no wake queues anybody, and the habit has every tick. LandAt is for a replay, where the answer is read off a file in a moment and has to be held until the boundary it landed on when it was made; a live worker leaves it at nought and the answer is taken at the first boundary after it arrives. What the scheduler does not do at a landing is judge: the six checks need a reading of the world, the village imports no law, and the boundary that called Take is the one that builds the reading and runs them.

▣ Build · stage 6 — ten tests, pinned, and the one that would hang
$ go test ./internal/village/ -run 'TestAWakeReturnsWhetherOrNotAWorkerIsThere|TestTheOrderIsByScoreThenIdentityAndReplays|TestAVillagerWaitingIsNotQueuedAgain|TestARequestPastTheCapIsDroppedUnasked|TestALateAnswerStopsTheAsking|TestAnAnswerIsTakenAtItsBoundaryAndNotBefore|TestAPersonInSightIsAReasonToThinkOnceAndNotAtEveryWake|TestADeadVillagerIsStruckFromTheQueue|TestTheShippedSchedulerIsACadenceTwoWeightsAndOneWorker|TestTheVillageStillImportsNeitherTheModelClientNorTheStore' -v
=== RUN   TestTheVillageStillImportsNeitherTheModelClientNorTheStore
    reflect_test.go:259: every file of the package read, and none of them names the model client or the store
--- PASS: TestTheVillageStillImportsNeitherTheModelClientNorTheStore (0.00s)
=== RUN   TestAWakeReturnsWhetherOrNotAWorkerIsThere
    schedule_test.go:65: no reader: one request into the slot, then a wake that handed nothing and said "every worker is busy; nothing handed"; a reader: the next queued at 150 handed at 250
--- PASS: TestAWakeReturnsWhetherOrNotAWorkerIsThere (0.00s)
=== RUN   TestTheOrderIsByScoreThenIdentityAndReplays
    schedule_test.go:100: faced 450, three events 110, stale alone 50; on a tie of 50, bodies 1, 2, 3
--- PASS: TestTheOrderIsByScoreThenIdentityAndReplays (0.00s)
=== RUN   TestAVillagerWaitingIsNotQueuedAgain
    schedule_test.go:128: body 1 handed at 150 is 'waiting' at 200 and out of the queue, which holds the other 2
--- PASS: TestAVillagerWaitingIsNotQueuedAgain (0.01s)
=== RUN   TestARequestPastTheCapIsDroppedUnasked
    schedule_test.go:152: two queued at 150, kept at 350, dropped unasked at 400 and queued afresh from 400, and no worker ever saw either
--- PASS: TestARequestPastTheCapIsDroppedUnasked (0.00s)
=== RUN   TestALateAnswerStopsTheAsking
    schedule_test.go:173: asked at 150, landed at 351; the wake at 400, with a worker reading, stopped: at tick 351 an answer asked for at tick 150 landed 201 ticks later, and the cap is 200: at this pace no answer can land in time, so the village runs the utility rule from here
--- PASS: TestALateAnswerStopsTheAsking (0.02s)
=== RUN   TestAnAnswerIsTakenAtItsBoundaryAndNotBefore
    schedule_test.go:191: held at 160, taken at 190, and the worker counted busy until it was
--- PASS: TestAnAnswerIsTakenAtItsBoundaryAndNotBefore (0.01s)
=== RUN   TestTheShippedSchedulerIsACadenceTwoWeightsAndOneWorker
    schedule_test.go:212: every 50 ticks, a memory worth 20 ticks, a person worth 400, 1 worker, under a cap of 200
--- PASS: TestTheShippedSchedulerIsACadenceTwoWeightsAndOneWorker (0.00s)
=== RUN   TestAPersonInSightIsAReasonToThinkOnceAndNotAtEveryWake
    schedule_test.go:241: in sight from 120: 450 at 150; answered at 160: 40 at 200 with the person still there; back into sight at 220: faced again at 250
--- PASS: TestAPersonInSightIsAReasonToThinkOnceAndNotAtEveryWake (0.01s)
=== RUN   TestADeadVillagerIsStruckFromTheQueue
    schedule_test.go:257: body 2 retired at 150 is in no order and no queue at 200; the queue holds body 3
--- PASS: TestADeadVillagerIsStruckFromTheQueue (0.00s)
PASS
ok  	theworld/internal/village	0.069s

The first of the nine new tests is the one the rule is held by, and it is a test that would hang rather than fail: it opens a scheduler with nobody reading the inbox, calls a wake, and waits two seconds for the call to come back. A wake that waited for a worker would never come back, the test would time out, and go test would report it, which is the one way a test can hold that something does not block. With one slot and nobody reading, the first wake puts one request in the slot and returns; the second finds the slot full, hands nothing, says so, and returns; then a reader takes the slot's request, answers it, and the next wake hands the head of the queue. The other eight are the order, the three refusals, the faced term clearing, a dead villager struck off, the file's numbers held against the cap, and the package's imports walked again with the tenth file in it.

Sixteen answers off the recording

The scheduler is driven by a loop, and the loop is the daemon's from volume 7 with the boundary filled in. Between every two ticks, in this order: the rows the witnesses closed are weighed, numbered and counted to the scheduler; who has a stranger in sight and whose reflection has come due are told to it; every answer that has landed is taken and judged over a reading of the world built now; every running plan posts its step's intent; and, on the cadence, the wake. Then the tick. Nothing in that list waits for a worker, and the worker is the only thing that waits for a model.

▣ Build · stage 7 — the boundary, in the order it runs, and the worker on the far side of it
// cmd/turns/loop.go — the boundary of tick now, elided to its order
func (l *loop) boundary(now int) error {
	rows, laid, err := l.s.drain(l.w)
	// ... the witnesses' rows, weighed and numbered
	// ...
	for id, n := range laid {
		l.sch.Noticed(id, n)
	}
	// ...
	for _, p := range l.w.people {
		if p.Body.Dead {
			// ... l.sch.Retire(p.Body.ID) ...
			continue
		}
		l.sch.Facing(p.Body.ID, now, l.w.faced(p.Name, now))
		if l.st.r.Due(p.Founded, now) {
			l.sch.Owe(p.Body.ID)
		}
	}
	// ...
	taken, l.held = l.sch.Take(now, l.held)
	for _, ld := range taken {
		if err := l.land(ld, now); err != nil {
			// ... the six checks over a reading taken now
			return err
		}
	}
	for _, p := range l.w.people {
		if r, ok := l.plans[p.Body.ID]; ok {
			if err := l.dispatch(p, r, now); err != nil {
			// ... one intent a tick into the mailbox
				return err
			}
		}
	}
	if l.sch.Due(now) && !l.closing {
		w := l.sch.Wake(now, l.prepare(now))
		l.showWake(w)
		// ...
	}
	return nil
}
// cmd/turns/worker.go — one worker, reading a request and two channels and nothing else
func worker(n int, st settingsOf, s *village.Scheduler, o oracle, made *ledgerOf, resident lang.Role) {
	for r := range s.Inbox {
		l := village.Landing{Request: r}
		t := time.Now()
		calls := &calls{resident: resident}
		var err error
		switch r.Job {
		case village.PlanJob:
			err = plan(st, r, o, calls, &l)
		case village.ReflectJob:
			err = reflect(st, r, o, calls, &l)
		case village.LineJob:
			err = line(st, r, o, calls, &l)
		default:
			err = fmt.Errorf("no job called %q", r.Job)
		}
		resident = calls.resident
		l.Loads = calls.loads
		if err != nil {
			l.Err = err.Error()
		}
		made.put(r, taken{worker: n, took: time.Since(t), gens: calls.gens, embeds: calls.embeds, vecs: calls.vecs, thoughtVecs: calls.thoughtVecs, landAt: o.landAt(r)})
		l.LandAt = o.landAt(r)
		s.Landings <- l
	}
}

The worker's three jobs are the last four chapters' cycles moved into a goroutine. A plan embeds the situation and, while the embedding model is the one resident, every row of the villager's stream that has no vector yet, then retrieves, renders and generates: two changes of model a plan, and the rows laid down since the last turn are embedded on the way, grouped with the embedding the plan makes anyway, which is finding 19 applied to the queue. A reflection is chapter 94's four phases, with the citation check run in the worker over the stream as it stood when the request was handed, and the accepted thoughts sent back as events for the boundary to weigh and number. A line is one generation on the hero model. The oracle behind all three is a live server or the committed recording, the same code either way, and the recording is what the rest of this section runs on.

The recording is one stretch of one village: a thousand ticks from the boundary of tick 2400, which is inside the committed day, at ten ticks a second, with a stranger stood in front of Ander at tick 3100 and every call the worker made written down with the tick its answer was taken at. The day up to 2400 is lived again from the founding, row by row, and the seventy-four rows it lays down are held against the fixture; from 2400 on the village lives a stretch it has not lived before, and every row after the seventy-fourth is this run's own. Sixteen turns, no model server anywhere, and every order, verdict and count below is the engine's.

▣ Build · stage 8 — the first wake: three scores of nought, and the tie broken on identity
// exemplars/exemplars.go — the embed line gains the recording, and a name for it
//go:embed chronicle.jsonl hero.header.json small.header.json vectors.json memories.jsonl memory-vectors.json reflections.json plans.json turns.json
var Files embed.FS
// exemplars/turns.go — create
// ...
const Turns = "turns.json"
$ go run ./cmd/turns -mode day | tail -214 | head -14
     #  who    job        stale events faced  score queued  did
     1  Halla  plan           0      0    no      0   2400  handed: 1 generation(s), 1 embedding(s), 2 load(s) at most
     2  Ander  plan           0      0    no      0   2400  queued
     3  Mose   plan           0      0    no      0   2400  queued
  tick   2437  Halla's plan landed: asked at 2400, 37 ticks in flight; 1 generation(s), 1 embedding(s), 2 load(s)
               Halla stands on 9,3 carrying 106.6876 grams, with 2 Ander in sight; the grounding set was 1 Halla, 2 Ander, 3 Mose
               the seam, at tick 2437 over the world as it stands: accepted
               2 step(s) spanning 60 ticks: go to 2,7; wait -
  tick   2450  wake 2: 1 with a worker, 2 queued after it
     #  who    job        stale events faced  score queued  did
     1  Ander  plan          50      1    no     70   2400  handed: 1 generation(s), 2 embedding(s), 2 load(s) at most
     2  Mose   plan          50      1    no     70   2400  queued
     3  Halla  plan           0      0    no      0   2450  queued
  tick   2491  Ander's plan landed: asked at 2450, 41 ticks in flight; 1 generation(s), 2 embedding(s), 2 load(s)

Three villagers enrolled at the same tick with nothing laid down for any of them score nought each, and the queue is Halla, Ander, Mose by identity: the tie-break on the page at the first wake, before any term has had time to move. Halla is handed, priced at one generation and one embedding and two changes of model; her answer lands thirty-seven ticks later, at 2437, and the seam is run at 2437 over a reading in which she is carrying 106.6876 grams and can see Ander, not at 2400. At the second wake Ander and Mose have each been stale fifty ticks and had one memory laid down, seventy each, and Ander's lower identity places him first; Halla's plan is running and her staleness is nought.

▣ Build · stage 9 — wakes 11 to 13: three reflections come due, priced at three generations, and one wake hands nothing
$ go run ./cmd/turns -mode day | tail -115 | head -22
  tick   2900  wake 11: 1 with a worker, 2 queued after it
     #  who    job        stale events faced  score queued  did
     1  Mose   reflection    53      0    no     53   2800  handed: 3 generation(s), 4 embedding(s), 3 load(s) at most
     2  Halla  reflection     0      1    no     20   2900  queued
     3  Ander  reflection     0      1    no     20   2850  queued
  tick   2901  Ander's plan ran out; the habit has the ticks until the next answer
  tick   2947  Halla's plan ran out; the habit has the ticks until the next answer
  tick   2950  wake 12: 1 with a worker, 2 queued after it
     #  who    job        stale events faced  score queued  did
     1  Ander  reflection    49      1    no     69   2850  queued
     2  Halla  reflection     3      1    no     23   2900  queued
     3  Mose                103      0    no    103      -  waiting
     every worker is busy; nothing handed
  tick   2979  Mose's reflection landed: asked at 2900, 79 ticks in flight; 3 generation(s), 3 embedding(s), 3 load(s)
               question 1: refused at the strict read: lang: qwen2.5:0.5b-instruct-q4_K_M answered with something that is no...
               question 2: accepted, at depth 1
               row 103 [thought] at tick 2900, weight 6, drawn from [92], a model's words: 92
  tick   3000  wake 13: 1 with a worker, 2 queued after it
     #  who    job        stale events faced  score queued  did
     1  Ander  reflection    99      1    no    119   2850  handed: 3 generation(s), 6 embedding(s), 3 load(s) at most
     2  Halla  reflection    53      1    no     73   2900  queued
     3  Mose   plan          21      0    no     21   3000  queued

Tick 2900 is two thousand ticks into three lives founded at 901, so at that boundary all three reflections come due and every queued plan becomes a reflection, priced at three generations and four embeddings and three changes of model. Mose's is handed, because his plan has been out fifty-three ticks and the others' are still running. At 2950 the worker is still on it: the wake ranks the two queued, marks Mose as waiting and out of the queue, and hands nothing, and the line under the table says so. Mose's reflection lands at 2979, seventy-nine ticks after it was asked; the first question's statement did not parse and was refused at the strict read, the second was accepted at depth 1 and appended as row 103, and the statement the model wrote for it is the number 92, which is what a model of this size made of the question and which nothing in the engine reads. At 3000 Ander is handed his, ninety-nine ticks stale; Halla, whose reflection has been queued since 2900, is second; and Mose is back in the queue for a plan.

▣ Build · stage 10 — wake 15: a stranger in sight is four hundred ticks, and Ander goes first
$ go run ./cmd/turns -mode day | tail -82 | head -19
  tick   3099  a stranger, body 4, stood on 6,2, one step along Ander's heading, carrying 100 grams off the flag
  tick   3100  wake 15: 1 with a worker, 2 queued after it
     #  who    job        stale events faced  score queued  did
     1  Ander  plan           5      1   yes    425   3100  handed: 1 generation(s), 3 embedding(s), 2 load(s) at most
     2  Halla  reflection   153      4    no    233   2900  queued
     3  Mose   plan         121      0    no    121   3000  queued
  tick   3141  Ander's plan landed: asked at 3100, 41 ticks in flight; 1 generation(s), 3 embedding(s), 1 load(s)
               2 row(s) of Ander's stream embedded on the way, so every row now has a vector
               Ander stands on 7,2 carrying 168.2468 grams, with 1 Halla in sight; the grounding set was 1 Halla, 2 Ander, 3 Mose, 4 a stranger
               the seam, at tick 3141 over the world as it stands: accepted
               2 step(s) spanning 60 ticks: go to 7,2; wait -
  tick   3150  dropped unasked: Halla's reflection, queued at tick 2900, 250 ticks ago, and the cap is 200
  tick   3150  wake 16: 1 with a worker, 2 queued after it
     #  who    job        stale events faced  score queued  did
     1  Halla  reflection   203      4    no    283   3150  handed: 3 generation(s), 8 embedding(s), 3 load(s) at most
     2  Mose   plan         171      0    no    171   3000  queued
     3  Ander  plan           0      0    no      0   3150  queued

The stranger is stood one step along Ander's heading at 3099, Ander's eyes return it at the boundary of 3100, and his score is 5 + 20 + 400 = 425 against Halla's 233, which is a reflection that has been queued for two hundred ticks. Ander goes first; that is what the term is for. His answer lands at 3141, and by then his heading has moved on and the stranger is out of his sight while Halla is in it; the grounding set stored with the proposal still carries body 4, because the set is what he could name when he was asked. At 3150 Halla's reflection has been queued 250 ticks, which is over the cap, and it is dropped unasked: no call was made for it, the worker never saw it, and the same wake queues her afresh from 3150 and, the worker being free, hands her at once. The drop cost the village nothing but the bookkeeping and it is what the second refusal is: a request that old is asked again from now, not from then.

▣ Build · stage 11 — Mose's plan dropped, Mose's plan landed, and Mose struck off
$ go run ./cmd/turns -mode day | tail -53 | head -10
  tick   3250  dropped unasked: Mose's plan, queued at tick 3000, 250 ticks ago, and the cap is 200
  tick   3250  wake 18: 1 with a worker, 2 queued after it
     #  who    job        stale events faced  score queued  did
     1  Mose   plan         271      0    no    271   3250  handed: 1 generation(s), 1 embedding(s), 2 load(s) at most
     2  Ander  plan          49      1    no     69   3150  queued
     3  Halla  plan          21      0    no     21   3250  queued
  tick   3280  Mose's plan landed: asked at 3250, 30 ticks in flight; 1 generation(s), 1 embedding(s), 1 load(s)
               Mose stands on 6,6 carrying 7.9358 grams, with nobody in sight; the grounding set was 1 Halla, 2 Ander, 3 Mose
               the seam, at tick 3280 over the world as it stands: accepted
               2 step(s) spanning 60 ticks: go to 6,6; wait -
$ go run ./cmd/turns -mode day | tail -27 | head -6
  tick   3352  Mose is dead on 6,6, by the rule that has killed every animal in this book, and is struck from the queue
  tick   3375  Ander's plan ran out; the habit has the ticks until the next answer
  tick   3392  Halla's plan landed: asked at 3350, 42 ticks in flight; 1 generation(s), 2 embedding(s), 2 load(s)
               1 row(s) of Halla's stream embedded on the way, so every row now has a vector
               Halla stands on 9,2 carrying 83.9915 grams, with 2 Ander in sight; the grounding set was 1 Halla, 2 Ander, 4 a stranger
               the seam, at tick 3392 over the world as it stands: accepted

Mose queued a plan at 3000, waited behind two reflections and a faced villager, and was dropped at 3250 and asked afresh, two hundred and seventy-one ticks stale. He is carrying 7.9358 grams when the answer lands at 3280, on the cell he has stood on since the founding with nothing in sight, and the plan the model wrote for him is to go to the cell he stands on and wait. It is accepted; the six checks have no term for a store. He starves on tick 3352 by the rule that has killed every animal in this book, the boundary finds his body dead and strikes him from the queue, and the last wake of the stretch ranks two people. The scheduler did not kill him. The habit found no plant in sight from 6,6 and spun him in place at the price of a turn a tick, the plans this model wrote kept him where he was, and nothing in the priority asks how much a villager is carrying. That last is a limit of the design as built, and the page says so where the run shows it.

▣ Build · stage 12 — what the stretch came to
$ go run ./cmd/turns -mode day | tail -19
  wakes                                                      20
  requests handed to a worker                                16
  answers landed                                             16
  ticks in flight, on average                                48
  of those, later than the cap                                0
  requests dropped unasked                                    2
  plans accepted at the seam                                 12
  plans refused at the seam                                   1
  steps refused when they came due                            0
  plans that ran out                                         11
  intents posted at the boundary                            649
  of those, taken out of a slot                             648
  ticks the villagers ran the habit                        2304
  memory rows laid down in the stretch                       42
  rows of the stream still without a vector                   5

  1000 ticks in 28ms, 35542 ticks a second (measured here; yours will differ)

  every order, verdict and count above is the engine's over the recording; the words in the answers are the model's

Twenty wakes, sixteen requests handed and sixteen answers landed, forty-eight ticks in flight on average, two dropped unasked, none later than the cap. Twelve plans accepted, one refused, and the refusal is the strict read: at 2713 the model wrote six steps against a cap of five. Six hundred and forty-nine intents posted at the boundary and six hundred and forty-eight taken out of a slot, the one left being the intent posted at the last boundary with no tick after it. Two thousand three hundred and four villager-ticks on the habit out of a possible three thousand, which is the floor chapter 91 built doing most of the work while the queue does the rest. And the same numbers, at the same ticks, every time this command is run, because every answer lands at the boundary it landed on when the recording was made and the queue is a function of the facts.

The boundary between two ticks, the scheduler on it, one worker beside it, and the mailbox the answer reaches the tick through A horizontal band across the top is the tick loop: tick, boundary, tick, boundary. Under one boundary a box lists what runs there in order: rows counted, who is in sight, answers taken and judged, steps posted, the wake. From the wake an arrow labelled a send that gives up runs down to a worker box at the bottom left, which is marked as calling the models. From the worker an arrow labelled a buffered channel runs up to a later boundary, where the answer is taken and judged over a reading of that boundary. From that boundary an arrow marked one intent a tick runs to a mailbox box, and from the mailbox a short arrow runs up into the following tick, marked a receive that gives up. A note at the right says the question was asked at one boundary and judged at a later one, and that the sixth check is what makes that safe. THE SCHEDULER LIVES ON THE BOUNDARY, THE WORKER OFF IT tick 2400 boundary tick 2401 … 35 ticks … tick 2437 boundary at the boundary, in order 1 rows counted 2 who is in sight 3 answers taken, judged 4 a step posted 5 the wake, on the cadence then the next tick a send that gives up one slot a worker the worker embeds, retrieves, generates a buffered channel; the boundary drains it with a receive that gives up, whenever it arrives at 2437, over 2437's reading the six checks; the sixth ages it from 2400: 37 ticks accepted: one intent a tick into the mailbox, 60 ticks the mailbox one slot, values, replace the tick reads the slot with a receive that gives up, and finding nothing, runs the habit asked at one boundary, judged at a later one: a decision about a world that has moved on
Figure 98.1 — Halla's first turn, as the recording has it. The wake at the boundary of tick 2400 hands one request to the worker with a send that gives up; the worker calls the models off the loop; the boundary of tick 2437 finds the answer, judges it over 2437's reading, and posts its first step into the mailbox, which the next tick reads with a receive that gives up. No tick waited on any of it.

Two hundred and fifty-three ticks without a thought

The live path is the same loop against the live models and the database: the day lived into the tables as it goes, the scheduler asking, one worker calling, every landing through the seam and into the ledger, and every duration on the page from here down measured on this machine, an eight-core AMD Ryzen 7 3700X with 30 GB of memory, rootless podman, the models answering on the processor with no graphics card in use; yours will differ, and so will a second run here, because when an answer lands depends on the wall clock and the queue moves with it. What does not differ is what is compared: every count, every verdict and every column of every row but the answer.

⚙ Tool — the model server, one model resident at a time, and a database that starts empty

The containers are the last four chapters': Ollama on the closed bridge with OLLAMA_MAX_LOADED_MODELS=1 and the three model files on a named volume, the Go code in world-go, and the database in world-db, which starts empty after podman kill and podman start because its data directory is a tmpfs, and which the live mode refuses if a village is already settled in it, because the numbers it gives its rows are the numbers an empty database gives them. The small model is loaded before the clock starts. The server's API reference is under github.com/ollama/ollama.

▣ Build · stage 13 — one worker, live, and what the ticks spent of their hundred milliseconds
$ podman kill world-db && podman start world-db
world-db
world-db
$ podman exec -w /bench world-go go run ./cmd/turns -mode live | tail -244 | head -6
  the day lived again from tick 901 to 2400 and into the tables as it went: 74 rows, 74 agree with the fixture row for row, 74 in the table, 74 vectors copied in
  the small model loaded before the clock starts, at 4096 tokens of context
  the village at the boundary of tick 2400
    Halla  body 1 on 9,3 carrying  109.6476 grams, alive, 20 rows in its stream
    Ander  body 2 on 7,2 carrying  180.2103 grams, alive, 33 rows in its stream
    Mose   body 3 on 6,6 carrying  179.7334 grams, alive, 21 rows in its stream
$ podman exec -w /bench world-go go run ./cmd/turns -mode live | tail -232 | head -5
  tick   2437  Halla's plan landed: asked at 2400, 37 ticks in flight; 1 generation(s), 1 embedding(s), 2 load(s); 3.629s on worker 1 (measured here; yours will differ)
               Halla stands on 9,3 carrying 106.6876 grams, with 2 Ander in sight; the grounding set was 1 Halla, 2 Ander, 3 Mose
               the seam, at tick 2437 over the world as it stands: accepted
               2 step(s) spanning 60 ticks: go to 2,7; wait -
               the row appended as proposal 1, accepted
$ podman exec -w /bench world-go go run ./cmd/turns -mode live | tail -28 | head -26
  wakes                                                      20
  requests handed to a worker                                16
  answers landed                                             16
  ticks in flight, on average                                48
  of those, later than the cap                                0
  requests dropped unasked                                    2
  plans accepted at the seam                                 12
  plans refused at the seam                                   1
  steps refused when they came due                            0
  plans that ran out                                         11
  intents posted at the boundary                            650
  of those, taken out of a slot                             649
  ticks the villagers ran the habit                        2303
  memory rows laid down in the stretch                       42
  rows of the stream still without a vector                   5
  generations the server was asked for                       22
  embeddings the server was asked for                        59
  calls that found their model not resident                  34
  memory rows in the table at the end                       119
  ledger rows, read back ORDER BY id                         13
  of those, accepted                                         12
  of those, refused                                           1

  1000 ticks in 1m40.003s, 10 ticks a second (measured here; yours will differ)
    inside the ticks and their boundaries: 134ms in all, 134µs a tick on average, 3.97ms the longest, of the 100ms each tick has
    on the workers' clock: 4.771s a request on average, 9.562s the longest, over 16 requests

The same seventy-four rows agree with the fixture, and the same village stands at 2400 carrying the same grams, because up to that boundary nothing has happened that did not happen when the day was recorded. From there the run is its own. Halla's first answer took 3.629 seconds on the worker's clock and landed at 2437, which is the tick the recording landed it at too, and on an idle processor this run's sixteen landings fell within a tick or two of the recording's all the way down, so the queue handed the same sixteen requests; a second run here lands them elsewhere and the queue moves with it. The line that is the chapter's claim is the last but one: over a thousand ticks held to ten a second, the ticks and their boundaries spent 134 milliseconds in all, 134 microseconds a tick on average and 3.97 milliseconds at the longest, of the hundred milliseconds each tick has, while a worker beside them spent 4.771 seconds a request on the models and 9.562 on the longest. No tick waited. The thirty-four calls that found their model not resident are the server's own count of evictions, one GET before every call, and they are the price the split is about: two a plan, three or four a reflection, and every one of them a load.

The hero model is the one call in this volume that earns seconds, because a person is standing there, and chapter 101 is where it is asked for a line. What this page measures is what that call does to everybody else. The bench issues one, off a flag, at the boundary of tick 2700, for Ander, as a stand-in for the line: a request of the third kind, put at the head of the queue, served by the same worker on the hero model at twenty-four tokens. Nobody is in the world to have been spoken to, and the answer is kept and not printed.

▣ Build · stage 14 — a line asked at 2700, two wakes that hand nothing, and a plan dropped while the small model was out
$ podman kill world-db && podman start world-db
world-db
world-db
$ podman exec -w /bench world-go go run ./cmd/turns -mode live -line 2700 | tail -144 | head -7
  tick   2700  a line is owed by Ander: a request for the hero model goes to the head of the queue
  tick   2700  wake 7: 1 with a worker, 2 queued after it
     #  who    job        stale events faced  score queued  did
     1  Ander  line           0      3    no     60   2700  queued
     2  Mose   plan         105      2    no    145   2550  queued
     3  Halla                54      8    no    214      -  waiting
     every worker is busy; nothing handed
$ podman exec -w /bench world-go go run ./cmd/turns -mode live -line 2700 | tail -131 | head -20
  tick   2750  wake 8: 1 with a worker, 2 queued after it
     #  who    job        stale events faced  score queued  did
     1  Ander  line          49      4    no    129   2700  handed: 1 generation(s), 0 embedding(s), 2 load(s) at most
     2  Mose   plan         155      2    no    195   2550  queued
     3  Halla  plan          37      0    no     37   2750  queued
  tick   2800  dropped unasked: Mose's plan, queued at tick 2550, 250 ticks ago, and the cap is 200
  tick   2800  wake 9: 1 with a worker, 2 queued after it
     #  who    job        stale events faced  score queued  did
     1  Mose   plan         205      2    no    245   2800  queued
     2  Halla  plan          87      1    no    107   2750  queued
     3  Ander                99      4    no    179      -  waiting
     every worker is busy; nothing handed
  tick   2850  wake 10: 1 with a worker, 2 queued after it
     #  who    job        stale events faced  score queued  did
     1  Mose   plan         255      2    no    295   2800  queued
     2  Halla  plan         137      1    no    157   2750  queued
     3  Ander               149      5    no    249      -  waiting
     every worker is busy; nothing handed
  tick   2876  Ander's line landed: asked at 2750, 126 ticks in flight; 1 generation(s), 0 embedding(s), 1 load(s); 12.59s on worker 1 (measured here; yours will differ)
               a line of 24 tokens from the hero model, kept and not printed: nobody is in the world to have been spoken to
$ podman exec -w /bench world-go go run ./cmd/turns -mode live -line 2700 | tail -15 | head -2
  the line: handed at tick 2750, landed at tick 2876; the next answer from the small model landed at tick 3003
  so the village did not think for 253 ticks at 10 ticks a second (measured here; yours will differ)

The line goes to the head of the queue at 2700, above Mose's plan at 145, and finds the worker busy with Halla's plan, so it waits one wake: a line is owed and not hurried, because nothing at the boundary waits. At 2750 it is handed, and the worker is on the hero model for 12.59 seconds, which is the load of 4,683,073,952 bytes of weights that evicts the small model, then twenty-four tokens: 126 ticks at ten a second. The wakes at 2800 and 2850 find the worker busy and hand nothing, and the table says so under Ander's name, marked waiting. At 2800 Mose's plan, queued at 2550, has waited 250 ticks and is dropped unasked, which is the eviction's second cost: a request that would have been served at 2750 has gone stale behind a line. The line lands at 2876; the next wake is 2900, where all three reflections come due, and the next answer from the small model is Mose's reflection at 3003, which paid four loads because the worker came to it holding the hero model. From the line's hand-off at 2750 to that landing is 253 ticks in which nobody in the village was answered by the small model: while somebody is being spoken to, the village stops thinking, and this is the number chapter 101 pays.

The third refusal needs the world run faster than a call can land inside the cap, and volume 7's unattended valley runs a hundred times faster than the watched pace and then some. The bench governs to a thousand ticks a second, so that a tick is one millisecond and a call of four seconds is four thousand ticks, and runs six thousand ticks so that the one answer lands inside the stretch.

▣ Build · stage 15 — a thousand ticks a second, one answer three thousand six hundred and fifty-six ticks late, and the asking stopped
$ podman kill world-db && podman start world-db
world-db
world-db
$ podman exec -w /bench world-go go run ./cmd/turns -mode live -hz 1000 -ticks 6000 -show 2400,2450,2650,6400 | tail -58 | head -26
  tick   2450  wake 2: 1 with a worker, 2 queued after it
     #  who    job        stale events faced  score queued  did
     1  Ander  plan          50      1    no     70   2400  queued
     2  Mose   plan          50      1    no     70   2400  queued
     3  Halla                50      0    no     50      -  waiting
     every worker is busy; nothing handed
  tick   2650  dropped unasked: Ander's plan, queued at tick 2400, 250 ticks ago, and the cap is 200
  tick   2650  dropped unasked: Mose's plan, queued at tick 2400, 250 ticks ago, and the cap is 200
  tick   2650  wake 6: 1 with a worker, 2 queued after it
     #  who    job        stale events faced  score queued  did
     1  Ander  plan         250      3    no    310   2650  queued
     2  Mose   plan         250      3    no    310   2650  queued
     3  Halla               250      0    no    250      -  waiting
     every worker is busy; nothing handed
  tick   3099  a stranger, body 4, stood on 6,2, one step along Ander's heading, carrying 100 grams off the flag
  tick   3264  Mose is dead on 6,6, by the rule that has killed every animal in this book, and is struck from the queue
  tick   6056  Halla's plan landed: asked at 2400, 3656 ticks in flight; 1 generation(s), 1 embedding(s), 2 load(s); 3.655s on worker 1 (measured here; yours will differ)
               Halla stands on 9,2 carrying 179.5164 grams, with nobody in sight; the grounding set was 1 Halla, 2 Ander, 3 Mose
               the seam, at tick 6056 over the world as it stands: refused by freshness: asked at tick 2400, and it is tick 6056: 3656 ticks old, and the cap is 200
               the row appended as proposal 1, refused
  tick   6056  the scheduler stopped asking: at tick 6056 an answer asked for at tick 2400 landed 3656 ticks later, and the cap is 200: at this pace no answer can land in time, so the village runs the utility rule from here
  tick   6400  wake 81: 0 with a worker, 0 queued after it
     #  who    job        stale events faced  score queued  did
     1  Ander  reflection  4000     45    no   4900      -  not asked
     2  Halla  reflection   344      3    no    404      -  not asked
     stopped: at tick 6056 an answer asked for at tick 2400 landed 3656 ticks later, and the cap is 200: at this pace no answer can land in time, so the village runs the utility rule from here
$ podman exec -w /bench world-go go run ./cmd/turns -mode live -hz 1000 -ticks 6000 -show 2400,2450,2650,6400 | tail -31 | head -18
  wakes                                                     120
  requests handed to a worker                                 1
  answers landed                                              1
  ticks in flight, on average                              3656
  of those, later than the cap                                1
  requests dropped unasked                                   17
  plans accepted at the seam                                  0
  plans refused at the seam                                   1
  steps refused when they came due                            0
  plans that ran out                                          0
  intents posted at the boundary                              0
  of those, taken out of a slot                               0
  ticks the villagers ran the habit                       12864
  memory rows laid down in the stretch                      117
  of those, after the scheduler stopped asking               47
  rows of the stream still without a vector                 117

  the scheduler stopped asking at tick 6056: at tick 6056 an answer asked for at tick 2400 landed 3656 ticks later, and the cap is 200: at this pace no answer can land in time, so the village runs the utility rule from here

One request handed at 2400 and one hundred and twenty wakes, every one of them finding the worker busy until the one answer landed. Ander's and Mose's requests are dropped at 2650, queued afresh, and dropped again every two hundred and fifty ticks, seventeen times between them, while the one call is in flight. The answer lands at 6056, 3,656 ticks after it was asked, which is 3.655 seconds at a thousand ticks a second, and the sixth check refuses it in the words it has for that: asked at 2400, it is 6056. The scheduler's own line follows on the same tick, and from there the village runs the utility rule; by wake 81 Ander's plan has become a reflection, two thousand ticks of a life having passed in two seconds, his score is four thousand nine hundred, and the wake ranks him and asks nobody. Thinking is the one thing in this world that cannot be sped up: the worker's clock is the wall clock, the world's is not, and at this pace the two do not meet inside the cap. What did not stop is the stream. A hundred and seventeen rows were laid down in the stretch, forty-seven of them after the asking stopped, and every one of the hundred and seventeen is in the table without a vector, because the vectors are made when a villager is next asked and nobody was. The village remembers a stretch it did not think through.

▣ Build · stage 16 — the daemon's ticks a second three ways on one ground, and the snapshot's luck part
$ go run ./cmd/turns -mode pace -ticks 20000 | tail -13
  20000 ticks in 75ms, 265687 ticks a second (measured here; yours will differ)

  villagers on the habit alone: 3 people, witnesses writing rows, the scheduler off
  20000 ticks in 197ms, 101769 ticks a second (measured here; yours will differ)
    580 rows laid down, 57280 ticks on the habit

  the scheduler running: the same people, the queue at every wake, every answer off the recording
  and through the seam at the boundary it landed on, the dispatcher posting intents
  20000 ticks in 250ms, 80008 ticks a second (measured here; yours will differ)
    400 wakes, 320 answers landed, 12980 intents posted, 840 rows laid down, 46080 ticks on the habit

  the third is the loop's own cost with nothing waited for: what a live model adds is
  measured by -mode live, where the ticks are held to the watched pace and timed inside it
$ go run ./cmd/turns -mode draws | tail -26
  on        1000 ticks from 2400: 20 wakes, 16 answers taken at the boundary, 649 intents posted, 2304 ticks on the habit

  part        off unpost     on  sha256 off         sha256 unposted    sha256 on         
  valley      753    753    753  64ccc86e490c4eac   64ccc86e490c4eac   3560df98a1f601b1  
  bed        3096   3096   3096  ae1b42796391cfa4   ae1b42796391cfa4   776ea64dd086d40e  
  stands      167    167    485  f5b3cbe130bdded5   f5b3cbe130bdded5   c302337de39853a4  
  bank       2280   2280   2248  5ed2f4b126d4b477   5ed2f4b126d4b477   3dc5ce70568add35  
  air          32     32     32  0d2a24b2a793b075   0d2a24b2a793b075   3ea3aec2c32490e4  
  pool        323    323    323  57ebc2ee63af0700   57ebc2ee63af0700   57ebc2ee63af0700  
  roster      475    475    475  fe553c3327488cb0   fe553c3327488cb0   8d23c93757b2dfb8  
  luck        518    518    518  f65504396694aa7a   f65504396694aa7a   ce0cf87f4d28a1f0  

  the luck part is the state of every stream the world reads, and all three villages read the same 9:
    8 seed flight
    9 germination
    10 plant mortality
    11 founding plants
    16 mutation
    17 crossover
    18 mate choice
    19 structural mutation
    20 birth placement
  off and unposted: the same 518 bytes of luck, part for part the same world; the scheduler woke 20 times,
  ranked, handed, took and judged, and drew nothing
  off and on: the luck differs, and so do 6 other parts: the villagers walked, ate and stood elsewhere,
  and a plant eaten or left standing is a plant that draws or does not, off the world's own streams

Three numbers, one ground, the same thousand ticks from the same boundary twenty times over from a fresh world each, ungoverned, so that the number is what the loop can do and not what it is held to: 265,687 ticks a second with no villagers, 101,769 with three people on the habit and the witnesses writing rows, and 80,008 with the scheduler running over the recording, the queue ranked at four hundred wakes and three hundred and twenty answers judged and dispatched. Each is measured here and yours will differ, on the machine named above, on the processor. The third is the loop's own cost with nothing waited for, because the answers come off the recording; what a live model adds is not a cost to the ticks at all, which is the 150 microseconds a tick above, but a cost to the worker, and the worker is off the loop. And the second run is the sentence this chapter owes about luck. Three villages over the same stretch: one that never scheduled, one that scheduled, judged every answer and posted none, and one that scheduled and posted. All three read the same nine streams, because the scheduler claims none. The first two are the same world to the byte, luck part included, because the scheduler woke twenty times, ranked, handed, took and judged, and drew nothing. The third differs from them in seven parts, luck among them, because its villagers walked, ate and stood elsewhere, and a plant eaten or left standing is a plant that draws or does not, off the world's own streams: that is the world's luck moving with the world, which is what it is for.

⚠ Worked failure — a second worker, run

The memory allows a hundred and forty-four and the file says one, so the obvious thing to try is two, and the bench tries it off a flag that prints itself as the counterfactual. Everything else is the same run as stage 13: the same stretch, the same models, the same machine within the same half hour.

$ podman kill world-db && podman start world-db
world-db
world-db
$ podman exec -w /bench world-go go run ./cmd/turns -mode live -workers 2 | tail -270 | head -20
  tick   2400  wake 1: 2 with a worker, 1 queued after it
     #  who    job        stale events faced  score queued  did
     1  Halla  plan           0      0    no      0   2400  handed: 1 generation(s), 1 embedding(s), 2 load(s) at most
     2  Ander  plan           0      0    no      0   2400  handed: 1 generation(s), 1 embedding(s), 2 load(s) at most
     3  Mose   plan           0      0    no      0   2400  queued
  tick   2436  Halla's plan landed: asked at 2400, 36 ticks in flight; 1 generation(s), 1 embedding(s), 2 load(s); 3.575s on worker 1 (measured here; yours will differ)
               Halla stands on 9,3 carrying 106.7676 grams, with 2 Ander in sight; the grounding set was 1 Halla, 2 Ander, 3 Mose
               the seam, at tick 2436 over the world as it stands: accepted
               2 step(s) spanning 60 ticks: go to 2,7; wait -
               the row appended as proposal 1, accepted
  tick   2450  wake 2: 2 with a worker, 1 queued after it
     #  who    job        stale events faced  score queued  did
     1  Mose   plan          50      1    no     70   2400  handed: 1 generation(s), 2 embedding(s), 2 load(s) at most
     2  Halla  plan           0      1    no     20   2450  queued
     3  Ander                50      1    no     70      -  waiting
  tick   2490  Ander's plan landed: asked at 2400, 90 ticks in flight; 1 generation(s), 1 embedding(s), 2 load(s); 8.974s on worker 2 (measured here; yours will differ)
               Ander stands on 7,2 carrying 179.8878 grams, with nobody in sight; the grounding set was 1 Halla, 2 Ander, 3 Mose
               the seam, at tick 2490 over the world as it stands: accepted
               2 step(s) spanning 60 ticks: go to 7,2; wait -
               the row appended as proposal 2, accepted
$ podman exec -w /bench world-go go run ./cmd/turns -mode live -workers 2 | tail -28 | head -26
  wakes                                                      20
  requests handed to a worker                                22
  answers landed                                             22
  ticks in flight, on average                                69
  of those, later than the cap                                0
  requests dropped unasked                                    0
  plans accepted at the seam                                 15
  plans refused at the seam                                   4
  steps refused when they came due                            0
  plans that ran out                                         12
  intents posted at the boundary                            703
  of those, taken out of a slot                             701
  ticks the villagers ran the habit                        2290
  memory rows laid down in the stretch                       55
  rows of the stream still without a vector                   2
  generations the server was asked for                       28
  embeddings the server was asked for                        84
  calls that found their model not resident                  48
  memory rows in the table at the end                       135
  ledger rows, read back ORDER BY id                         19
  of those, accepted                                         15
  of those, refused                                           4

  1019 ticks in 1m41.904s, 10 ticks a second (measured here; yours will differ)
    inside the ticks and their boundaries: 177ms in all, 173µs a tick on average, 4.55ms the longest, of the 100ms each tick has
    on the workers' clock: 6.925s a request on average, 14.201s the longest, over 22 requests

Start from the symptom. Two requests are handed at the first wake, and Halla's lands in 3.575 seconds while Ander's, asked at the same tick on the other worker, takes 8.974. Nothing about Ander's prompt is dearer; his worker embedded while hers generated, the embedding model evicted the small model under her, hers loaded it back under him, and two calls that take three and a half seconds each alone took three and a half and nine. Reason from there to what the whole run shows. Twenty-two answers landed against sixteen with one worker, which is more, and nothing was dropped unasked where one worker dropped two; and every answer waited longer for it: 69 ticks in flight on average against 48, 6.925 seconds a request against 4.771, the longest 14.201 seconds, a reflection that was 143 ticks in flight and fifty-seven short of the cap, and the run overran its stretch by nineteen ticks waiting for the last answer. Forty-eight calls found their model not resident against thirty-four, which is the two workers evicting each other. So a second worker bought six more answers a thousand ticks and paid for each of them with forty-four per cent more waiting and fourteen more loads. Run once more with another job on the processor, which is a run this page does not quote, a reflection under two workers took 311 ticks to land and the scheduler stopped asking for the rest of the stretch; one worker on the same loaded processor stayed under the cap. The cause is the sentence the budget mode printed: memory allows many, residency allows one model, and two workers on one resident model are two workers taking turns to load. The file says one, and this is what it was set from: the answers a second worker buys are bought from the margin under the cap, and the margin is what an accelerated world spends first.

▣ Build · stage 17 — nothing durable is in flight: volume 7's kill, unaltered, and the snapshot's eight names
$ podman kill world-db && podman start world-db
world-db
world-db
$ podman exec -w /bench world-go sh -c '/tmp/weeks -mode run -ticks 36000 -save 3600 -tape /tmp/weeks-80/killed-80.tape -die-at 19500; echo "exit status $?"' | tail -3
weeks: killed inside the creature phase of tick 19500
Killed
exit status 137
$ podman exec -w /bench world-go /tmp/weeks -mode same -dir /tmp/weeks-80 -seam 18000 | tail -18 | head -5
weeks: killed and restarted, against run straight through

                                               bytes  sha256, first 16
  run straight through                          1080  19f96bd7c7acf846
  killed and restarted                          1080  19f96bd7c7acf846
$ go test ./internal/store/ -run 'TestASnapshotIsEightPartsAndNoOthers|TestASaveOnEveryBoundaryChangesNothing|TestARestartFromAnOlderSaveLandsOnTheNewer' -v
=== RUN   TestASaveOnEveryBoundaryChangesNothing
    keep_test.go:32: 200 saves taken between ticks, not one number moved, and 200 ticks on both worlds are at 8c501a6b2c3d0342
--- PASS: TestASaveOnEveryBoundaryChangesNothing (0.61s)
=== RUN   TestARestartFromAnOlderSaveLandsOnTheNewer
    keep_test.go:78: restored from the older save, run 200 ticks, and all 8 parts came out the newer one: 314685 bytes
--- PASS: TestARestartFromAnOlderSaveLandsOnTheNewer (0.16s)
=== RUN   TestASnapshotIsEightPartsAndNoOthers
    save_test.go:211: 8 parts, every one of them once, and 280901 bytes between them
--- PASS: TestASnapshotIsEightPartsAndNoOthers (0.10s)
PASS
ok  	theworld/internal/store	0.883s

Volume 7's daemon, built from this module, killed inside the creature phase of tick 19500 with SIGKILL and restarted out of the database, writes the same tape to the byte as the run nobody killed: 1,080 bytes, one digest, ten lines the same. The digests are this module's own, because chapter 90 widened the action table and every wiring in that valley grew with it; what holds is that the killed run and the straight run agree, which is the test as volume 7 wrote it and not a line of it changed. The three store tests are pinned to their names and say the same thing from the other side: a snapshot is the eight parts volume 7 named and no ninth, a save on every boundary moves nothing, and a restart from an older save lands on the newer. Nothing the scheduler holds is in any of those parts. A request in the queue, a request with the worker, an answer in the channel and an intent in a mailbox are all lost when the process is killed, and the villager falls back to the habit, which is what the fallback is for; everything a villager is lives in tables or is derived from them, and the queue is derived from them at the next boundary of the next process.

Why the worker boundary passes values

Take the village away and what is left is a way of putting something slow beside something that must not stop. The loop has one place where nothing is part way through, and everything that is not a tick happens there: the count of what happened, the offer of one request, the taking of whatever has come back. The offer and the taking are the two operations in the design that could wait, and neither is allowed to: the offer is a put into a slot that is either free or not, and the taking is a drain of a channel that is either holding something or not. Every other operation is arithmetic over values the boundary already holds. The worker sees a request and two channels, and a request is a copy of what the world looked like when the request was handed; the worker cannot reach the roster, cannot block the boundary, and cannot be blocked by it, because the channel it puts answers on has room.

The second thing that generalizes is the two clocks on a request, and it is what makes the sixth check the safety of the whole design rather than a filter on the end of it. A request is aged from the tick it was queued, and the queue drops it unasked when that age passes the cap, because the worker's time is the scarce thing and a call whose answer the seam will refuse should not be made. A proposal is aged from the tick it was asked, and the seam refuses it when that age passes the cap, because the world's state is the thing the answer is about. The recording has no landing refused for age and two requests dropped for it, which is the queue doing the seam's refusing before the call, and the accelerated run below has one landing refused for age and the asking stopped, which is the seam catching what the queue could not. Neither clock is the wall clock: the worker measured seconds, the boundary counted ticks, and only the ticks reached a verdict.

The third is the score as a sum in one unit, and it is a smaller point with a measured reason behind it. A term that is in ticks can be added to staleness, which is in ticks, and a reader can check the queue on paper: 5 + 20 + 400 is 425 at wake 15 and 153 + 80 is 233, and Ander goes first. A term that does not clear is a term that hands the worker to one villager, which the first draft of the faced term did for four wakes running. The order the queue prints is total because the last comparison is on identity, and it replays because every term is a count the boundary keeps and none is a clock or a draw; the snapshot's luck part is the proof that nothing drew, and the pace is the proof of what the arithmetic costs.

Checkpoint

✓ Checkpoint — one worker, a queue of three, and a village that cannot be hurried
  • Work out from the three sums how many further conversations of the small model fit under the ceiling at 4,096 tokens, and say why the file says one worker when the memory would allow a hundred and forty-four.
  • Compute the score of each villager at wake 15 from the three terms and the two weights, place them, and say which villager the tie-break would have put first had two scores been equal.
  • Name the two ticks a request carries, say which of the two refusals ages a request from each, and say what the recording shows dropped at 3150 and why the same wake asked for the same villager again.
  • Read the wake at 2950 and say why it handed nothing, why Mose is marked waiting and out of the queue, and what a wake that waited for the worker instead would have done to the ticks.
  • Given the one-worker and two-worker runs, say what the second worker bought in answers landed, what it cost in ticks in flight, how close its longest request came to the cap, and what the count of calls that found their model not resident says about why.
  • Say, from the accelerated run, which landing stopped the asking, how many rows were laid down after it stopped, and why those rows are in the table without a vector.
⚡ Exercises — try first, then reveal
Exercise 1 — a person is worth less than a stale plan. Set faced in the scheduler block to 100 and run the shipped test that reads the block. Predict the message before you run it, then put 400 back.

TestTheShippedSchedulerIsACadenceTwoWeightsAndOneWorker fails with a person in front is worth 100 ticks and the cap is 200: a person could be outranked by a stale plan. The test pins the weight above the cap because a villager can be at most 200 ticks stale before its request is dropped and asked afresh, so a person worth less than 200 could lose to a plan that has merely run out; at 400 a person in sight outranks any staleness the queue can hold. Put 400 back and the test passes. Replay the recording under 100 and wake 15 places Halla's reflection at 233 above Ander at 125, the worker is handed a request the tape has no turn for, and every landing from there is an error, in the same words exercise 3 shows.

Exercise 2 — a wake every twenty ticks. Run the replay with -every 20 and read the error, then explain from the round-trip arithmetic what a cadence of twenty would change and what it would not.

The replay stops before the first tick: the recording was made from tick 2400 every 50 ticks with 1 worker(s), and this run is from 2400 every 20 with 1. A recording is a recording of one cadence. Run live instead and the round does not shorten: a plan still takes thirty to forty ticks and a reflection eighty, so most wakes find the worker busy, hand nothing, and print the line that says so, and the one thing that moves is how soon after an answer lands the next request is handed, from up to fifty ticks later to up to twenty. The cadence sets how long a free worker sits idle, never how fast the answers come.

Exercise 3 — the stretch with nobody to face. Replay the recording with -stranger 0 and predict, before running, the first wake at which the replay and the recording part.
$ go run ./cmd/turns -mode day -stranger 0 | tail -62 | head -5
  tick   3100  wake 15: 1 with a worker, 2 queued after it
     #  who    job        stale events faced  score queued  did
     1  Halla  reflection   153      4    no    233   2900  handed: 3 generation(s), 8 embedding(s), 3 load(s) at most
     2  Mose   plan         121      0    no    121   3000  queued
     3  Ander  plan           5      0    no      5   3100  queued

Fourteen wakes replay to the tick, because up to 3099 the stranger was not in the world and the two runs are the same world. At 3100 Ander scores 5: no person in sight, and no memory laid down either, because the row the recording's Ander had at that wake was the sighting. Halla's reflection at 233 is handed instead, the tape holds no reflection for Halla asked at 3100, and the worker's landing carries the error the recording holds no reflection for Halla asked at tick 3100; -mode record makes one; so does every landing after it, and with no plan posted the habit spins Mose to death at 3309 instead of 3352. A recording is a recording of one world, and the first tick the worlds differ is the first tick the tape has nothing to say.

A stranger stood in front of Ander at tick 3099, and at 3100 the queue put him first and the model was asked what he does next: he walked to the cell he was standing on and waited. The hero model was asked once on this page for what he might say, and the answer was kept in a field nothing reads, because a line that reaches a reader needs a face to be said from and a box to be said in, and the village has neither. What it has is three people whose turns come round on a cadence a reader can count, a worker that answers when it answers, and a seam that judges every answer against the world it lands in; and a stretch of a thousand ticks, recorded once, in which all of that ran and not one tick waited.