When step == 0, this loop starts as many map tasks it can wrt
maxTasksPerJob
When step == 1, this loop starts as many reduce tasks it can wrt
maxTasksPerJob
When step == 2, this loop starts as many map tasks it can
When step == 3, this loop starts as many reduce tasks it can

It may seem that we would improve this loop by queuing jobs we cannot
start in steps 0 and 1 because of maxTasksPerJob, and using that queue
in step 2 and 3.
A first thing to notice is that the time with the current algorithm is
logarithmic, because it is the sum of (p^k) for k from 1 to N, were
N is the number of jobs and p is the probability for a job to not exceed
limits The probability for the cache to be useful would be similar to
p^N, that is 1/(e^N), whereas its size and the time spent to manage it
would be in ln(N).
So it is not a good idea.