Calling a cmdlet comes at a cost. Just because you use Start-Sleep -Milliseconds 1
, doesn't mean it's going to take 1ms. This is because that cmdlet has overhead it needs to take care of behind the scenes, like setting up the timer, instantiating objects, etc.
Measure-Command { Start-Sleep -Milliseconds 1 }
# TotalMilliseconds : 25.1157
See the above...even though I told it to only run for 1ms, it still took 25ms because of the overhead. This overhead won't be exactly the same every time, but you should always expect there to be some.
On my computer, it seems to average about 16ms of overhead per call. So if you run that 1000 times, then on average, it's going to take 16 seconds to run, just for the sleep alone.
I obtained the average by running this a few times:
Measure-Command { 1..100 | % { Start-Sleep -Milliseconds 1 } }
It's like driving a car. You don't just hop in a car and go, you need to start it up first, and there's things going on behind the scenes the car needs to do in order to start. And that takes a little bit of time.