Dynamic chunk sizing

Introducing `Doxport\Util\Chunk`:

The contract is:
 - The caller provides an initial estimate of the chunk size
 - The caller provides a *target* (wallclock) time, each chunk should take about this long to perform
 - The critical/timed section is wrapped in `begin()`/`end()` calls
 
Given this, `getEstimatedSize()` will return a suitable exponentially-weighted moving average of the size of chunk to attempt. The size estimate will vary to try and keep the time taken within the critical section to the target.
Not stored as factors, but as the actual max and min, based on the estimate; too much trouble to abstract the default factors, they're pretty throw-away.