-
Notifications
You must be signed in to change notification settings - Fork 100
Space leak with collisions #254
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Hey @ndmitchell, since you've probably thought about this more than any of us, would you mind submitting a patch fixing this? @sjakobi and I are now in the swing of helping @treeowl clear out the backlog (modulo a few permissions wibbles that need to be sorted), and we can review whatever you give us ASAP. |
Another option we use some places is to use an unboxed unary tuple as the result of the passed function. Then we can handle strict and lazy uniformly without this sort of leak. I think that's probably better. |
@treeowl sounds like a cool technique, but not one I'm familiar with. I read the code, but it's not immediately obvious to me what it does. Is it documented somewhere? Or in some notes? |
A boxed unary tuple looks like this: data Box a = Box {unBox :: a}
deriving KitchenSink This looks a lot like class Funktor f where
funkMap :: (a -> Box b) -> f a -> f b A typical instance ties unpacking the results to building the spine: instance Funktor [] where
funkMap f = go where
go [] = []
go (x : xs)
| Box y <- f x
= y : go xs Now you can define map, map' :: Funktor f => (a -> b) -> f a -> f b
map f = funkMap (Box . f)
map' f = funkMap (\x -> Box $! f x)
replace :: Funktor f => a -> f b -> f a
replace x = funkMap (const (Box x)) Just one underlying mapping function, and no space leaks! The trouble is that these |
* #254, avoid space leak with collisions * Add a regression test
Given the following program:
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 thatupdateOrSnocWith
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 isconst
ignored. One remedy, at the cost of duplicating code, so to write a dedicatedupdateOrSnoc
that skips the function call entirely, as anything else is likely to overly-force values in the .Lazy case.The text was updated successfully, but these errors were encountered: