
Ian Lynagh wrote:
[moving to glasgow-haskell-bugs]
On Wed, Nov 15, 2006 at 11:40:12PM +0000, Neil Davies wrote:
however when -threaded is used you get some interesting effects, including returning too early:
Tgt/Actual = 0.000125/0.000034s, diff = -0.000091s
Thanks for the report; I can reproduce it on Linux/amd64.
OK, so the bug here is that threadDelay n might return after less than n microseconds.
This looks like it's caused by truncation problems when converting times to ticks (where a tick is 1/50 of a second), e.g. while trying to sleep for 1.953125s one run started at 1164157960.773726s which is (Int) 1164157960 * 50 + 773726 * 50 / 1000000 = (Int) 58207898038.6863 = 58207898038 ticks and woke the thread up at 1164157962.708609s which is (Int) 1164157962 * 50 + 708609 * 50 / 1000000 = (Int) 58207898135.4305 = 58207898135 ticks
The difference is 58207898135 - 58207898038 = 97 ticks.
Meanwhile we're trying to sleep for (Int) 50 * 1.953125 = (Int) 97.65625 = 97 ticks
However, 1164157962.708609s - 1164157960.773726s = 1.93488311767578s which is 0.0182418823242201s too short.
The problem is that we have counted 0.6863 ticks before the start time, not counted 0.4305 ticks before the finish time and have been waiting 0.65625 ticks too short a time. Thus we have counted (0.6863-0.4305 + 0.65625) / 50 == 0.018241 too much time.
I think the answer is that
let target = now + usecs `quot` tick_usecs
in GHC/Conc.lhs should be
let target = 1 + now + (usecs + tick_usecs - 1) `quot` tick_usecs
I'm also a bit dubious about the use of the constant "50" for the number of ticks per second, but the results with +RTS -V0.001 don't look any more wrong so perhaps I just need to get some sleep.
The hardcoded 50 in GHC/Conc.lhs matches up with TICK_FREQ in libraries/base/includes/HsBase.h. It could probably be made larger without any ill effects. I agree that we should round up the target time to the nearest tick rather than rounding down, though. Cheers, Simon