Skip to content

Performance regression from GHC 8.4.4 to GHC 8.6.4

Summary

Function becomes slower when compiled with latest GHC

Steps to reproduce

Here is a sample program:

{-# LANGUAGE DeriveFunctor #-}

module Main (main) where

import           Criterion.Main

data ListF a b = Cons a b
               | Nil
               deriving (Functor)

elgot :: Functor f => (f a -> a) -> (b -> Either a (f b)) -> b -> a
elgot φ ψ = h where h = either id (φ . fmap h) . ψ

collatzLength :: Integral a => a -> a
collatzLength = elgot algebra elgotCoalgebra
    where algebra Nil        = 0
          algebra (Cons _ x) = x + 1
          elgotCoalgebra 1 = Left 1
          elgotCoalgebra n
             | n `mod` 2 == 0 = Right $ Cons n (div n 2)
             | otherwise = Right $ Cons n (3 * n + 1)

main :: IO ()
main =
    defaultMain [ bgroup "collatzLength"
                      [ bench "collatzLength" $ nf collatzLength (837799 :: Int) ]
                ]

The relevant bits are in that module proper but I used criterion for benchmarks.

When run with GHC 8.6.4 I get

Benchmark elgot-bench-bench: RUNNING...
benchmarking collatzLength/collatzLength
time                 1.453 μs   (1.447 μs .. 1.460 μs)
                     1.000 R²   (1.000 R² .. 1.000 R²)
mean                 1.448 μs   (1.442 μs .. 1.456 μs)
std dev              23.46 ns   (19.43 ns .. 30.54 ns)
variance introduced by outliers: 16% (moderately inflated)

Benchmark elgot-bench-bench: FINISH

whereas with GHC 8.4.4 I get

Benchmark elgot-bench-bench: RUNNING...
benchmarking collatzLength/collatzLength
time                 1.110 μs   (1.103 μs .. 1.117 μs)
                     1.000 R²   (1.000 R² .. 1.000 R²)
mean                 1.106 μs   (1.104 μs .. 1.110 μs)
std dev              11.54 ns   (9.112 ns .. 16.53 ns)

Benchmark elgot-bench-bench: FINISH

Expected behavior

I would expect the code compiled with GHC 8.6.4 to have similar performance to the code compiled with GHC 8.4.4.

Environment

  • GHC version used: GHC 8.6.4

Optional:

  • Operating System: Lubuntu
  • System Architecture: x86_64

(Aside: there's a darcs repo I'm using for other purposes that anyone wishing to verify may use)

Edited by vanessamchale
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information