DRMacIver's Notebook
Reducer Pass Budgeting
Reducer Pass Budgeting
One of the hard problems in designing test-case reducers is pass ordering: You’ve split the reducer up into a number of different passes, now you want to know what order to run them in.
A lot of why this is tricky is that some passes you just really don’t want to run until you have to because they’re much more expensive. I’m currently exploring a solution to this problem that mostly avoids it by just making that not the case.
The solution is budgeting - running a reduction pass with a maximum number of calls it’s allowed to make.
The following algorithm seems to work fairly well:
- Set the budget to infinity, mark all passes as active.
- For each active reduction pass:
- Run it, but halt it once it has made a number of unsuccessful calls that exceed the current budget.
- If it succeeded, set the budget to something appropriate. I’m currently trying double the mean number of calls made by a successful pass on this run through.
- If it failed, mark the pass as inactive.
- If the number of active passes is one or fewer, mark all passes as active.
- If no passes made progress, halt (note that the budget is infinite unless a pass has made progress, so this doesn’t affect correctness). Otherwise go back to step 2.
This seems to do a pretty decent job of keeping the badly behaved passes under control while still making good progress.
Other things I have tried:
- Starting the budget low and working upwards causes a lot of wasted work.
- Being more aggressive with lowering the budget on each pass does the same.
- Allowing just a single pass to remain active tends to result in a lot of pointless small shrinks and not much useful progress.