Except it is not a loop[1], but a non-tail recursive function (with dual calls), if the compiler can optimise that to a loop that is actually impressive.
Most likely function call overhead (and in the slower cases, interpreter overhead) is probably what is being measured in the best case.
[1] In that it won't be a jump and check style loop.