Skip to content

Space leak with collisions #254

Closed
@ndmitchell

Description

@ndmitchell

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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions