Skip to content

Performance regression in overloading

The following program goes 25% slower with HEAD compared to 6.12.3:

module Main (main) where

import DeepSeq

main :: IO ()
main = do
  rnf [ mk x | x <- [ 1 .. 1024 ] ] `seq` return ()
  where
    mk :: Float -> [(Float,Float)]
    mk x = [ (x+i,x+i+1) | i <- [ 1 .. 2048] ]

using the attached DeepSeq module, or indeed the standard Control.DeepSeq.

Simon and I diagnosed the problem to be the following dictionary for NFData (Float,Float) (this is HEAD):

Main.main6 :: DeepSeq.NFData (GHC.Types.Float, GHC.Types.Float)
Main.main6 =
  DeepSeq.$fNFData(,)
    @ GHC.Types.Float
    @ GHC.Types.Float
    DeepSeq.$fNFDataFloat
    DeepSeq.$fNFDataFloat

GHC has not inlined the dictionary function or the arguments here, even though this class is in fact just a single-method dictionary. With 6.12 we got:

Main.main6 =
  \ (ds_dBc :: (GHC.Types.Float, GHC.Types.Float)) ->
    case ds_dBc of _ { (x_awr, y_aws) ->
    case x_awr of _ { GHC.Types.F# _ ->
    case y_aws of _ { GHC.Types.F# _ -> GHC.Unit.() }
    }
    }

i.e. everything fully inlined and a nice efficient definition.

This is currently affecting parallel programs where we typically use rnf quite a lot.

Trac metadata
Trac field Value
Version 6.13
Type Bug
TypeOfFailure OtherFailure
Priority high
Resolution Unresolved
Component Compiler
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information