
#12781: Significantly higher allocation with INLINE vs NOINLINE -------------------------------------+------------------------------------- Reporter: MikolajKonarski | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 Resolution: | Keywords: Operating System: Linux | Architecture: x86_64 Type of failure: Runtime | (amd64) performance bug | Test Case: Blocked By: | Blocking: Related Tickets: #12747 #12603 | Differential Rev(s): #5775 | Wiki Page: | -------------------------------------+------------------------------------- Changes (by simonpj): * cc: maurerl@…, pdownen@…, ariola@… (added) Comment: Interesting. I know exactly what is going on. With `NOINLINE dis` we get {{{ dis = \p. let $w$j ww = blah in case p of -1# -> $w$j (...) DEFAULT -> $w$j (..) go xs z = case xs of [] -> ... (y:ys) -> case dis y of () -> go ys z }}} Note that `$w$j` is a join point, so incurs no allocation cost. There is just one call to `dis` in the body of `go`. So without the `NOINLINE dis`, the function `dis` inlines in the body of `go`. But then we get something like {{{ go xs z = case xs of [] -> ... (y:ys) -> let $w$j ww = blah in case p of -1# -> case ($w$j (...)) of () -> go ys z DEFAULT -> case ($w$j (...)) of () -> go yz z }}} Yikes! `$w$j` is no longer a join point, so allocation goes up. Six months ago I would have felt sad. But today I feel happy. In our paper [https://www.microsoft.com/en-us/research/publication/compiling- without-continuations/ Compiling without continuations], we explain how to ensure that join points are never destroyed. Moreover, Luke Maurer is well advanced on a full implementation in GHC. Luke, how is it going? When will it land in GHC? We need this! This ticket would make a lovely example to add to the paper, because it's a true "from the wild" example. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12781#comment:5 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler