[GHC] #427: Random.StdGen slowness

GHC trac at galois.com
Fri Jan 13 06:37:31 EST 2006


#427: Random.StdGen slowness
-----------------------------+----------------------------------------------
  Reporter:  remit           |          Owner:  nobody  
      Type:  bug             |         Status:  assigned
  Priority:  low             |      Milestone:          
 Component:  libraries/base  |        Version:  6.4.1   
  Severity:  normal          |     Resolution:  None    
  Keywords:                  |             Os:  Unknown 
Difficulty:  Unknown         |   Architecture:  Unknown 
-----------------------------+----------------------------------------------
Changes (by simonmar):

  * architecture:  => Unknown
  * difficulty:  => Unknown
  * version:  None => 6.4.1
  * os:  => Unknown

Old description:

> {{{
> Two (performance) problems in one:
>
> {-# OPTIONS -fffi #-}
> module Main (main) where
>
> import Control.Monad
> import Random
>
> foreign import ccall unsafe "random" _crandom :: IO Int
>
> randomInt :: (Int, Int) -> IO Int
> randomInt (min,max) = do
>     n <- _crandom
>     return $ min + n `rem` range
>     where
>         range = max - min + 1
>
> main = replicateM_ (5*10^6) $ do
>     x <- randomRIO (0::Int,1000) :: IO Int
>     x `seq` return ()
>     return ()
>
> First, without the "seq" at the end, hardly anything is
> evaluated and we're building huge amounts of thunks.
> Three ideas about this one:
> - Blame the user :)
> - data StdGen = StdGen !Int !Int
>   Use strict fields in StdGen. Doesn't actually help
> (at least in this example).
> - Force evaluation of the StdGen in getStdRandom.
>   Does help in this example, but also changes behaviour
> of the library:
>   x <- randomRIO undefined
>   currently dies only when x (or the result of a later
> randomRIO) is evaluated. This change causes it to die
> immediately.
>
> Second, even _with_ the "seq", replacing "randomRIO" by
> "randomInt" speeds the thing up with a factor of about
> 30. (2 to 3.6, in a "real world" university practicum
> exercise of 900 lines of code)
> Even given the fact that they're not really doing the
> same thing, this seems rather much :(
> }}}

New description:

 {{{
 Two (performance) problems in one:

 {-# OPTIONS -fffi #-}
 module Main (main) where

 import Control.Monad
 import Random

 foreign import ccall unsafe "random" _crandom :: IO Int

 randomInt :: (Int, Int) -> IO Int
 randomInt (min,max) = do
     n <- _crandom
     return $ min + n `rem` range
     where
         range = max - min + 1

 main = replicateM_ (5*10^6) $ do
     x <- randomRIO (0::Int,1000) :: IO Int
     x `seq` return ()
     return ()

 First, without the "seq" at the end, hardly anything is
 evaluated and we're building huge amounts of thunks.
 Three ideas about this one:
 - Blame the user :)
 - data StdGen = StdGen !Int !Int
   Use strict fields in StdGen. Doesn't actually help
 (at least in this example).
 - Force evaluation of the StdGen in getStdRandom.
   Does help in this example, but also changes behaviour
 of the library:
   x <- randomRIO undefined
   currently dies only when x (or the result of a later
 randomRIO) is evaluated. This change causes it to die
 immediately.

 Second, even _with_ the "seq", replacing "randomRIO" by
 "randomInt" speeds the thing up with a factor of about
 30. (2 to 3.6, in a "real world" university practicum
 exercise of 900 lines of code)
 Even given the fact that they're not really doing the
 same thing, this seems rather much :(
 }}}

-- 
Ticket URL: <http://cvs.haskell.org/trac/ghc/ticket/427>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the Glasgow-haskell-bugs mailing list