19d15287

Created Started Cancelled

Start the most expensive mutation groups first

Stacked on #156, because the baselines it sorts by are the map that one reads once per run. Independent of #157.

A group waits for a slot, so the order the groups are handed to the runner in is the order they get one, and today that is the manifest's order.

The groups of a run differ by orders of magnitude, because a group costs whatever the covering tests it runs cost. Per-child wall over 150 random mutations of one large run: median 1.05 s, mean 5.64 s, p99 91 s, max 155 s, with the top 5 of those 150 accounting for 62% of the total. Handed over last, one of those few holds a slot while every other slot stands idle.

Sorting by cost descending leaves that child in the middle of the run instead. The cost is the sum of the covering tests' baselines, which is what the per-mutation budgets are derived from as well. It is an estimate either way, since a mutation stops at the test that kills it and which test that is is not known until it has run; nothing but the order children start in depends on it, and the index each group is reported under travels with it, so the report is unchanged.

### Tests

`scheduleGroups` is exported and tested directly: the dearer group comes first with its index, and a run with no baselines keeps the order it came in. Note what that does not cover: the tests pin the function, not that `runMutationMode` calls it, which I checked by hand (removing the call leaves them green). The same is true of `writeChildTask` in #156, and the alternative in both cases was a spawned shell stand-in.

### What it does not change

No verdict, no budget, and no reported order. On a single-slot run, or a run whose groups all cost the same, it is a no-op.