[GHC] #9398: Data.List.cycle is not a good producer

GHC ghc-devs at haskell.org
Mon Aug 4 09:20:59 UTC 2014


#9398: Data.List.cycle is not a good producer
-------------------------------------+-------------------------------------
              Reporter:  dfeuer      |            Owner:
                  Type:  bug         |           Status:  new
              Priority:  normal      |        Milestone:  7.8.4
             Component:              |          Version:  7.8.3
  libraries/base                     |         Keywords:
            Resolution:              |     Architecture:  Unknown/Multiple
      Operating System:              |       Difficulty:  Easy (less than 1
  Unknown/Multiple                   |  hour)
       Type of failure:  Runtime     |       Blocked By:
  performance bug                    |  Related Tickets:
             Test Case:              |
              Blocking:              |
Differential Revisions:              |
-------------------------------------+-------------------------------------

Comment (by nomeata):

 Don’t be discouraged! I think this is very much worth it, and if people
 use `cycle` in list comprehensions (which they likely do), there might be
 real-world benefit in this. We just need to avoid regressions.

 I tried to reproduce your findings. I do observe the higher allocation,
 but the accumulator `Int#` is still unboxed. The extra allocations seem to
 stem from the `ys1` allocated here:

 {{{
 Rec {
 go :: [GHC.Types.Int] -> GHC.Prim.Int# -> GHC.Types.Int
 go =
   \ (ds :: [GHC.Types.Int]) ->
     case ds of _ {
       [] -> Main.main_cyc;
       : y ys ->
         let {
           ys1 :: GHC.Prim.Int# -> GHC.Types.Int
           ys1 = go ys } in
         \ (eta :: GHC.Prim.Int#) ->
           case GHC.Prim.tagToEnum# (GHC.Prim.<=# eta 1) of _ {
             GHC.Types.False ->
               case y of _ { GHC.Types.I# x ->
               case ys1 (GHC.Prim.-# eta 1) of _ { GHC.Types.I# y1 ->
               GHC.Types.I# (GHC.Prim.+# (GHC.Prim.*# x 13) y1)
               }
               };
             GHC.Types.True ->
               case y of _ { GHC.Types.I# x -> GHC.Types.I# (GHC.Prim.*# x
 13) }
           }
     }

 Main.main_cyc :: GHC.Prim.Int# -> GHC.Types.Int
 Main.main_cyc = go lvl9
 end Rec }
 }}}

 This is an interesting case. It seems to be a shortcoming in the call
 arity analysis: One might think it should be able to infer that `go` is
 always called with two arguments (and hence move the `\eta` out of the
 `let` and `case`).

 But it (rightfully) doesn’t do that because `main_cyc` is a thunk, and
 eta-expanding it would duplicate the case analysis done by `case ds`.

 The regular arity analysis also refuses to improve that code, for a
 similar reason: It considers to move the `\eta` up, but it would escape
 the `let ys1`, and the arity analysis is unable to determine if that would
 be expensive or not.

 Interesting case!

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


More information about the ghc-tickets mailing list