[Haskell-cafe] More fun with micro-benchmarks and optimizations. (GHC vs Perl)

Don Stewart dons at galois.com
Wed Jul 23 17:00:12 EDT 2008


brad.larsen:
> And against gawk 3.1.5:
> 
> $ time awk -F: '{sum += 1 / $2} END{print sum}' test.out
> 3155.63
> 
> real    0m0.197s
> user    0m0.184s
> sys     0m0.004s
> 
> compared to Don's Haskell version:
> 
> $ time ./fastSum < test.out
> 3155.626666664377
> 
> real    0m0.072s
> user    0m0.056s
> sys     0m0.004s
> 
> compared to the Corey's perl version:
> 
> $ time perl Sum.pl
> Duration (sec): 3155.62666666438
> 
> real    0m0.181s
> user    0m0.164s
> sys     0m0.012s
> 

Another variant, using a non-copying readDouble (available in
bytestring-lexing package 0.1.2),

    {-# OPTIONS -fbang-patterns #-}

    import qualified Data.ByteString.Char8  as S
    import qualified Data.ByteString.Unsafe as S
    import Data.ByteString.Lex.Double

    main = print . go 0 =<< S.getContents
      where
        go :: Double -> S.ByteString -> Double
        go !n !s = case unsafeReadDouble s' of
            Nothing     -> n
            Just (k,t)  -> let delta = 1 / k in go (n+delta) t
          where
            s' = case S.elemIndex ':' s of
                Nothing -> S.empty
                Just i  -> S.unsafeDrop (i+2) s

Computes in:

    $ time ./Fast < test.out
    3155.626666664377
    ./Fast < test.out  0.02s user 0.00s system 80% cpu 0.025 total

So that's probably a good place to stop.

Note the general rules:

  * strict bytestrings
  * tight tail-recursive loops with strict, atomic accumulators
  * non-copying parsing.

-- Don


More information about the Haskell-Cafe mailing list