[GHC] #10034: Regression in mapM_ performance

GHC ghc-devs at haskell.org
Mon Feb 2 00:54:04 UTC 2015


#10034: Regression in mapM_ performance
-------------------------------------+-------------------------------------
        Reporter:  dfeuer            |                   Owner:  ekmett
            Type:  bug               |                  Status:  new
        Priority:  normal            |               Milestone:  7.10.1
       Component:  Core Libraries    |                 Version:  7.10.1-rc2
      Resolution:                    |                Keywords:
Operating System:  Unknown/Multiple  |            Architecture:
 Type of failure:  Runtime           |  Unknown/Multiple
  performance bug                    |               Test Case:
      Blocked By:                    |                Blocking:
 Related Tickets:                    |  Differential Revisions:  Phab:D632
-------------------------------------+-------------------------------------

Comment (by dfeuer):

 Replying to [comment:1 simonpj]:
 > Can you offer a reproducible test case, and timing or allocation data?

 I had one, and then I lost it. I wish I could give you one as a test case
 and for future analysis. It was something very simple, and the `mapM_` of
 4.7 was consistently the same as the version in the linked differential,
 and both allocated less than the version currently in head. I believe it
 had to be an arity issue. Call arity wasn't catching it for some reason,
 so it needed input from the other arity analysis that it wasn't getting.
 Consider the current definition:

 {{{#!hs
 mapM_ f = foldr ((>>) . f) (return ())
 }}}

 Taking apart the argument to `foldr` above gives

 {{{#!hs
 mapM_ f = foldr (\m -> (>>) (f m)) (return ())
 }}}

 Now fuse this with `build g`:

 {{{#!hs
 mapM_ f (build g) = g (\m -> (>>) (f m)) (return ())
 }}}

 Without knowing what the monad is, `mapM_` doesn't know that `(>>)` has
 arity 2, and relies on Call Arity analysis of `g`, which I imagine wasn't
 working in whatever example I was dealing with. What I propose below
 forces the arity up to 2, and is also significantly easier to read.

 {{{#!hs
 {-# INLINE mapM_ #-}
 mapM_ f = foldr (\m n -> f m >> n) (return ())
 }}}

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10034#comment:2>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list