[GHC] #11735: Optimize coercionKind

GHC ghc-devs at haskell.org
Mon Jan 29 09:03:57 UTC 2018


#11735: Optimize coercionKind
-------------------------------------+-------------------------------------
        Reporter:  goldfire          |                Owner:  (none)
            Type:  task              |               Status:  new
        Priority:  normal            |            Milestone:
       Component:  Compiler          |              Version:  7.10.3
      Resolution:                    |             Keywords:
Operating System:  Unknown/Multiple  |         Architecture:
 Type of failure:  Compile-time      |  Unknown/Multiple
  performance bug                    |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:                    |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------

Comment (by tdammers):

 Replying to [comment:40 goldfire]:
 > Sorry, still confused. :(
 >
 > How are `coercionKind` and `coercionRole` ''mutually'' recursive? I see
 that `coercionRole` calls `coercionKind` but not the other way around.

 Sorry for the confusion, I shouldn't be trying to explain things I only
 half understand myself when tired.

 Looking at HEAD on `master`, we have the `coercionKindRole` function that
 is simply recursive for NthCo, and has the `nth` call embedded. So for
 nested NthCo's, its behavior should be quadratic.

 The un-refactored version has `coercionKind`, which is simply recursive
 (O(n)), and we have `coercionRole`, which recurses via `coercionKindRole`.
 The latter is really just a matter of calling `coercionKind` and
 `coercionRole` individually though; the `coercionRole` call makes
 `coercionRole` simply recursive (O(n)), but the `coercionKind` call
 introduces another O(n), making the entire thing also quadratic.

 Calling this "mutually recursive" is of course a brainfart on my side,
 since `coercionKind` never calls back into `coercionRole`.

 So in terms of big-O, HEAD and "un-refactored" should be the same. Why one
 perfoms better than the other is somewhat unclear to me though.

 > But you're right that I'm trying to understand better why there's a
 performance improvement in this patch (even before any caching). In the
 nested `NthCo` case, I'm pretty sure your refactor would be worse. But in
 the test case at hand (which I assume doesn't have nested `NthCo`s --
 haven't looked), your change is clearly an improvement.
 >
 > However, I don't think your analysis above is really the problem. I
 would expect that the running time of `coercionKind` or `coercionRole` on
 nested `NthCo`s to be linear in the sum of the `d`s -- that is, we'll have
 to add together all the indices. You've shown above that the old recursion
 pattern (from `coercionKindRole`) traverses down the linked list twice
 (once in `getNth` and once in `nthRole`), but this shouldn't change
 asymptotic complexity. And, usually, `d` is quite small, and so I wouldn't
 expect this to show up at all, really. I still don't think we've quite
 gotten to the bottom of why separating out `coercionKind` and
 `coercionRole` should effect a performance improvement.

 Indeed, it's not the problem, or rather, the un-refactoring alone doesn't
 fix anything - if it makes a difference at all, then it's most likely just
 a constant-factor improvement, nothing fundamental. But that's not why we
 did it anyway; the reason we did it was so that we could more easily
 implement the caching (storing precalculated roles in the NthCo itself),
 which breaks down one of the linear terms to constant.

 > On the other hand, the separated version really is quadratic... and yet
 it's faster (on this test case)! That's the conundrum.

 Yes, but we don't know if it's actually big-O-faster, or just happens have
 a more favorable constant factor.

 > Please don't let my nit-picking slow you down or discourage you. It's
 just that I think you've hit something quite interesting, and, well, I'm
 interested. :)


 Absolutely not, your input has been super helpful, and I much prefer hard
 criticism over empty praise. Bring it on :)

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


More information about the ghc-tickets mailing list