Haskell ThreadDelay issue (GHC) on Ubuntu

I noticed strange behavior with the threadDelay function in GHC.Conc on some of my machines. The following program:

main = do print "start"
          threadDelay (1000 * 1000)
          print "done"

1 second is required, as expected. On the other hand, this program:

{-# LANGUAGE BangPatterns #-}
import Control.Concurrent

main = do print "start"
          loop 1000
          print "done"
  where loop :: Int -> IO ()
        loop !n =
          if n == 0 
          then return ()
          else do threadDelay 1000
                  loop (n-1)

it takes about 10 seconds to work on my two machines, although on other machines it takes about 1 second, as expected. (I compiled both of the above programs with the '-threaded' flag.) Here is a screenshot from Threadscope showing that there is activity only once every 10 milliseconds:Screenshot of ThreadScope showing that threadDelay of 1 millisecond sleeps for 10 milliseconds.

On the other hand, here is a screenshot from ThreadScope from one of my machines on which the program takes 1 second in total: Screenshot of ThreadScope showing that threadDelay of 1 millisecond sleeps for about 1 milliseconds.

Similar C program:

#include <unistd.h>
#include <stdio.h>

int main() {
  int i; 
  for (i=1; i < 1000; i++) {
    printf("%i\n",i);
    usleep(1000);
  }
  return 0;
}

does the right thing, i.e. running "time. / a.out" gives output, for example:

1
2
...
999

real 0m1.080s
user 0m0.000s
sys  0m0.020s

- , , ? ghc 7.2.1 Linux (x86_64) Ubuntu. Ubuntu 10.04.2, 11.04.

+5
3

threadDelay . promises, , , , , , . , - , - . ( , , Unix ' .)

+3

, '-threaded'. ( 6.12.3 30 .)

+1

, threadDelay , , , . Haskell .

, .

, threadDelays. :

module Main where
import Control.Concurrent
import Data.Time

time op = 
    getCurrentTime >>= \ t0 -> 
    op >> 
    getCurrentTime >>= \ tf -> 
    return $! (diffUTCTime tf t0)

main :: IO ()
main = 
    let action tm = time (threadDelay tm) >>= putStrLn . show in
    mapM action [2000,5000,10000,20000,30000,40000,50000] >>
    return ()

:

0.0156098s
0.0156098s
0.0156098s
0.0312196s
0.0312196s
0.0468294s
0.0624392s

, getCurrentTime 15,6 . 1000 1000, 15.6 , .

Ubuntu (11.04, 2.6.38-11) (~ 100us).

Perhaps you can avoid synchronization problems by keeping the program more busy, so we don't turn off the context. In any case, I would suggest that you do not use threadDelay for synchronization, or at least check the time and perform any operations up to a given point.

Your high-precision sleep through C may work for you if you want nasty things with FFI, but you should use related threads (at least for your timer).

+1
source

All Articles