Haskell: performance difference from different functions?

The following code:

import Control.Exception import Data.List updateAverage :: (Fractional t) => (t, t) -> t -> (t, t) updateAverage (old_value, old_counter) x = let new_counter = old_counter + 1 in assert(new_counter /= 0) old_value `seq` (old_value + (x - old_value) / new_counter, new_counter) average values = fst (foldl' updateAverage (0.0, 0.0) values) -- version I main = do let v = [1 .. 1000000] let a = average v putStrLn (show a) 

gets faster (compilation options: ghc.exe -O3 ) when I replace the definition of average with the function

 average = fst . foldl' updateAverage (0.0, 0.0) -- version II 

What could be the reason for this? I thought the differences between the two lines are mostly syntax. Is it easier to optimize the second version (without the free variable values )?

Oddly enough, when compiling without optimization, the version I get faster.

Sync Results:

: -O3

version I: 0.280s version II: 0.212s

: (without optimization)

version I: 0.42s version II: 0.44s

Measured using the time shell command in Cygwin.

Synchronization results with type = Double:

Double

: -O3

version I: 0.22s version II :: 0.212s

: (without optimization)

version I: 0.34 s version II: 0.35 s

Additional Information: I am using a compiler

 > $ ghc -v Glasgow Haskell Compiler, Version 7.0.4, for Haskell 98, > stage 2 booted by GHC version 6.12.2 Using binary package database: > C:\Program Files\Haskell > Platform\2011.4.0.0\lib\package.conf.d\package.cache wired-in package > ghc-prim mapped to ghc-prim-0.2.0.0-e1f7c380581d61d42b0360d440cc35ed > wired-in package integer-gmp mapped to > integer-gmp-0.2.0.3-91607778cf3ae8f3948a50062b4f8479 wired-in package > base mapped to base-4.3.1.0-f520cd232cc386346843c4a12b63f44b wired-in > package rts mapped to builtin_rts wired-in package template-haskell > mapped to template-haskell-2.5.0.0-7d9b1443ac5ab69e5ed705a487990deb > wired-in package dph-seq not found. wired-in package dph-par not > found. Hsc static flags: -static > *** Deleting temp files: Deleting: > *** Deleting temp dirs: Deleting: ghc.exe: no input files Usage: For basic information, try the `--help' option. under Cygwin.* 
+7
source share
1 answer

I suppose something could happen to flow or merge in a loop. Perhaps there is a rewrite rule deeply immersed in the Prelude, which shoots in one case or not in another. Or, because you do not say how much faster, you can just see the effects of the cache.

If you want to know more, learn how to fish:

  • Use ghc -ddump-simpl to see the generated code and compare it.

  • Use valgrind to count the number of instructions to execute.

If nothing else, these tools will provide you with enough information so that you can ask a more focused detailed question.

+3
source

All Articles