loop() runs at no particular rate, its just called from a loop (whose only other actions are checking
for serial input - basically an empty loop() will get called 100k times a second or more easily.
If you want timing to be fixed, you have to use hardware to it, either via interrupts (common approach
for sampled systems), or by busy-waiting and checking the current time from micros().
Relying on the natural timing of the code is very fragile - an upgrade of the system could easily involve
changes to the compiler which then cause the code to be faster or slower than before without any changes
to the source.
On a more complex processor with caching the timing consistency is completely out of the window...