Closed
Description
Given the following program:
import qualified Data.HashMap.Strict as Map
import Data.IORef
import Data.Hashable
import Control.Monad
newtype Wrapper a = Wrapper a
deriving Eq
instance Hashable (Wrapper a) where
hashWithSalt _ _ = 0
main = do
mp <- newIORef $ Map.fromList [(Wrapper 0, "0"), (Wrapper 1, "1")]
forM_ [1..1000000000] $ \i -> do
modifyIORef' mp $ Map.insert (Wrapper 2) (show i)
It leaks about 1Gb/s when compiled with -O
. It is an example cut down from Ghcide, haskell/ghcide#586, where it leaks 30Mb/s. The issue is that updateOrSnocWith
lazily applies a function to the key, the old value, and the new value. In the case of inserting with a collision, the only relevant values are the old values, and everything else is const
ignored. One remedy, at the cost of duplicating code, so to write a dedicated updateOrSnoc
that skips the function call entirely, as anything else is likely to overly-force values in the .Lazy case.