RE: performance regressions

2014-12-17 Thread Simon Peyton Jones
If you use INLINEABLE, that should make the function specialisable to a 
particular monad, even if it's in a different module. You shouldn't need INLINE 
for that.

I don't understand the difference between cases (2) and (3).

I am still suspicious of why there are so many calls to this one function that 
it, alone, is allocating a significant proportion of compilation of the entire 
run of GHC.  Are you sure there isn't an algorithmic improvement to be had, to 
simply reduce the number of calls?

Simon

|  -Original Message-
|  From: ghc-devs [mailto:ghc-devs-boun...@haskell.org] On Behalf Of
|  Richard Eisenberg
|  Sent: 16 December 2014 21:46
|  To: Joachim Breitner
|  Cc: ghc-devs@haskell.org
|  Subject: Re: performance regressions
|  
|  I've learned several very interesting things in this analysis.
|  
|  - Inlining polymorphic methods is very important. Here are some data
|  points to back up that claim:
| * Original implementation using zipWithAndUnzipM:8,472,613,440
|  bytes allocated in the heap
| * Adding {-# INLINE #-} to the definition thereof:   6,639,253,488
|  bytes allocated in the heap
| * Using `inline` at call site to force inlining: 6,281,539,792
|  bytes allocated in the heap
|  
|  The middle step above allowed GHC to specialize zipWithAndUnzipM to my
|  particular monad, but GHC didn't see fit to actually inline the
|  function. Using `inline` forced it, to good effect. (I did not collect
|  data on code sizes, but it wouldn't be hard to.)
|  
|  By comparison:
| * Hand-written recursion:6,587,809,112 bytes allocated in the
|  heap
|  Interestingly, this is *not* the best result!
|  
|  Conclusion: We should probably add INLINE pragmas to Util and
|  MonadUtils.
|  
|  
|  - I then looked at rejiggering the algorithm to keep the common case
|  fast. This had a side effect of changing the zipWithAndUnzipM to
|  mapAndUnzipM, from Control.Monad. To my surprise, this brought
|  disaster!
| * Using `inline` and mapAndUnzipM:7,463,047,432 bytes
|  allocated in the heap
| * Hand-written recursion: 5,848,602,848 bytes
|  allocated in the heap
|  
|  That last number is better than the numbers above because of the
|  algorithm streamlining. But, the inadequacy of mapAndUnzipM surprised
|  me -- it already has an INLINE pragma in Control.Monad of course.
|  Looking at -ddump-simpl, it seems that mapAndUnzipM was indeed getting
|  inlined, but a call to `map` remained, perhaps causing extra
|  allocation.
|  
|  Conclusion: We should examine the implementation of mapAndUnzipM (and
|  similar functions) in Control.Monad. Is it as fast as possible?
|  
|  
|  
|  In the end, I was unable to bring the allocation numbers down to where
|  they were before my work. This is because the flattener now deals in
|  roles. Most of its behavior is the same between nominal and
|  representational roles, so it seems silly (though very possible) to
|  specialize the code to nominal to keep that path fast. Instead, I
|  identified one key spot and made that go fast.
|  
|  Thus, there is a 7% bump to memory usage on very-type-family-heavy
|  code, compared to before my commit on Friday. (On more ordinary code,
|  there is no noticeable change.)
|  
|  Validating my patch locally now; will push when that's done.
|  
|  Thanks,
|  Richard
|  
|  On Dec 16, 2014, at 10:41 AM, Joachim Breitner  wrote:
|  
|  > Hi,
|  >
|  >
|  > Am Dienstag, den 16.12.2014, 09:59 -0500 schrieb Richard Eisenberg:
|  >> On Dec 16, 2014, at 4:01 AM, Joachim Breitner  wrote:
|  >>
|  >>> another guess (without looking at the code, sorry): Are they in
|  the
|  >>> same module? I.e., can GHC specialize the code to your particular
|  Monad?
|  >
|  >> No, they're not in the same module. I could also try moving the
|  >> zipWithAndUnzipM function to the same module, and even specializing
|  >> it by hand to the right monad.
|  >
|  > I did mean zipWithAndUnzipM, so maybe yes: Try that.
|  >
|  > (I find it hard to believe that any polymorphic monadic code should
|  > perform well, with those many calls to an unknown (>>=) with a
|  > function parameter, but maybe I'm too pessimistic here.)
|  >
|  >
|  >> Could that be preventing the fusing?
|  >
|  > There is not going to be any fusing here, at least not list fusion;
|  > that would require your code to be written in terms of functions
|  with
|  > fusion rules.
|  >
|  > Greetings,
|  > Joachim
|  >
|  > --
|  > Joachim "nomeata" Breitner
|  >  m...@joachim-breitner.de * http://www.joachim-breitner.de/
|  >  Jabber: nome...@joachim-breitner.de  * GPG-Key: 0xF0FBF51F  Debian
|  > Developer: nome...@debian.org
|  >
|  > ___
|  > ghc-devs mailing list
|  > ghc-devs@haskell.org
|  > http://www.haskell.org/mailman/listinfo/ghc-devs
|  
|  ___
|  ghc-devs mailing list
|  ghc-devs@haskell.org
|  http://www.haskell.org/mailman/listinfo/ghc

RE: type-checker regression in GHC HEAD?

2014-12-17 Thread Simon Peyton Jones
Ah yes!  A palpable bug thank you.  Fixing..

S

|  -Original Message-
|  From: Herbert Valerio Riedel [mailto:hvrie...@gmail.com]
|  Sent: 17 December 2014 10:01
|  To: Simon Peyton Jones
|  Cc: Edward Kmett; Austin Seipp
|  Subject: Re: type-checker regression in GHC HEAD?
|  
|  Hello Simon,
|  
|  ...does that repro-case work for you? shall I create a Trac ticket as
|  well? I consider this one quite critical for this week's GHC 7.10.1
|  RC, if it can't compile `lens` :-/
|  
|  Cheers,
|hvr
|  
|  On 2014-12-16 at 15:03:49 +0100, Herbert Valerio Riedel wrote:
|  > On 2014-12-16 at 14:33:00 +0100, Simon Peyton Jones wrote:
|  >> No immediate bells.
|  >>
|  >> Is it possible to reproduce it without compiling all lens's zillion
|  >> dependencies?
|  >
|  > it's actually easier to isolate than expected:
|  >
|  >   {-# LANGUAGE UndecidableInstances #-}
|  >
|  >   import Control.Applicative
|  >   import Control.Category
|  >   import Prelude hiding ((.),id)
|  >
|  >   newtype FocusingPlus w k s a = FocusingPlus { unfocusingPlus :: k
|  > (s, w) a }
|  >
|  >   instance Functor (k (s, w)) => Functor (FocusingPlus w k s) where
|  > fmap f (FocusingPlus as) = FocusingPlus (fmap f as)
|  >
|  >   instance Applicative (k (s, w)) => Applicative (FocusingPlus w k
|  s) where
|  > pure = FocusingPlus . pure
|  > FocusingPlus kf <*> FocusingPlus ka = FocusingPlus (kf <*> ka)
|  >
|  >
|  > works with GHC 7.8, fails with GHC HEAD w/
|  >
|  >   repro.hs:13:25:
|  > Couldn't match type ‘f0’ with ‘k (s, w)’
|  >   ‘f0’ is untouchable inside the constraints () bound by the
|  type signature for pure :: a -> FocusingPlus w k s a at repro.hs:13:3-
|  6
|  > Expected type: a -> k (s, w) a
|  >   Actual type: a -> f0 a
|  > Relevant bindings include pure :: a -> FocusingPlus w k s a
|  (bound at repro.hs:13:3)
|  > In the second argument of ‘(.)’, namely ‘pure’
|  > In the expression: FocusingPlus . pure
|  >   Failed, modules loaded: none.
|  
|  --
|  "Elegance is not optional" -- Richard O'Keefe
___
ghc-devs mailing list
ghc-devs@haskell.org
http://www.haskell.org/mailman/listinfo/ghc-devs


Re: performance regressions

2014-12-17 Thread Richard Eisenberg
By unsubstantiated guess is that INLINEABLE would have the same effect as 
INLINE here, as GHC doesn't see fit to actually inline the function, even with 
INLINE -- the big improvement seen between (1) and (2) is actually 
specialization, not inlining. The jump from (2) to (3) is actual inlining. 
Thus, it seems that GHC's heuristics for inlining aren't working out for the 
best here.

I've pushed my changes, though I agree with Simon that more research may 
uncover even more improvements here. I didn't focus on the number of calls 
because that number didn't regress. Will look into this soon.

Richard

On Dec 17, 2014, at 4:15 AM, Simon Peyton Jones  wrote:

> If you use INLINEABLE, that should make the function specialisable to a 
> particular monad, even if it's in a different module. You shouldn't need 
> INLINE for that.
> 
> I don't understand the difference between cases (2) and (3).
> 
> I am still suspicious of why there are so many calls to this one function 
> that it, alone, is allocating a significant proportion of compilation of the 
> entire run of GHC.  Are you sure there isn't an algorithmic improvement to be 
> had, to simply reduce the number of calls?
> 
> Simon
> 
> |  -Original Message-
> |  From: ghc-devs [mailto:ghc-devs-boun...@haskell.org] On Behalf Of
> |  Richard Eisenberg
> |  Sent: 16 December 2014 21:46
> |  To: Joachim Breitner
> |  Cc: ghc-devs@haskell.org
> |  Subject: Re: performance regressions
> |  
> |  I've learned several very interesting things in this analysis.
> |  
> |  - Inlining polymorphic methods is very important. Here are some data
> |  points to back up that claim:
> | * Original implementation using zipWithAndUnzipM:8,472,613,440
> |  bytes allocated in the heap
> | * Adding {-# INLINE #-} to the definition thereof:   6,639,253,488
> |  bytes allocated in the heap
> | * Using `inline` at call site to force inlining: 6,281,539,792
> |  bytes allocated in the heap
> |  
> |  The middle step above allowed GHC to specialize zipWithAndUnzipM to my
> |  particular monad, but GHC didn't see fit to actually inline the
> |  function. Using `inline` forced it, to good effect. (I did not collect
> |  data on code sizes, but it wouldn't be hard to.)
> |  
> |  By comparison:
> | * Hand-written recursion:6,587,809,112 bytes allocated in the
> |  heap
> |  Interestingly, this is *not* the best result!
> |  
> |  Conclusion: We should probably add INLINE pragmas to Util and
> |  MonadUtils.
> |  
> |  
> |  - I then looked at rejiggering the algorithm to keep the common case
> |  fast. This had a side effect of changing the zipWithAndUnzipM to
> |  mapAndUnzipM, from Control.Monad. To my surprise, this brought
> |  disaster!
> | * Using `inline` and mapAndUnzipM:7,463,047,432 bytes
> |  allocated in the heap
> | * Hand-written recursion: 5,848,602,848 bytes
> |  allocated in the heap
> |  
> |  That last number is better than the numbers above because of the
> |  algorithm streamlining. But, the inadequacy of mapAndUnzipM surprised
> |  me -- it already has an INLINE pragma in Control.Monad of course.
> |  Looking at -ddump-simpl, it seems that mapAndUnzipM was indeed getting
> |  inlined, but a call to `map` remained, perhaps causing extra
> |  allocation.
> |  
> |  Conclusion: We should examine the implementation of mapAndUnzipM (and
> |  similar functions) in Control.Monad. Is it as fast as possible?
> |  
> |  
> |  
> |  In the end, I was unable to bring the allocation numbers down to where
> |  they were before my work. This is because the flattener now deals in
> |  roles. Most of its behavior is the same between nominal and
> |  representational roles, so it seems silly (though very possible) to
> |  specialize the code to nominal to keep that path fast. Instead, I
> |  identified one key spot and made that go fast.
> |  
> |  Thus, there is a 7% bump to memory usage on very-type-family-heavy
> |  code, compared to before my commit on Friday. (On more ordinary code,
> |  there is no noticeable change.)
> |  
> |  Validating my patch locally now; will push when that's done.
> |  
> |  Thanks,
> |  Richard
> |  
> |  On Dec 16, 2014, at 10:41 AM, Joachim Breitner  |  breitner.de> wrote:
> |  
> |  > Hi,
> |  >
> |  >
> |  > Am Dienstag, den 16.12.2014, 09:59 -0500 schrieb Richard Eisenberg:
> |  >> On Dec 16, 2014, at 4:01 AM, Joachim Breitner  |  breitner.de> wrote:
> |  >>
> |  >>> another guess (without looking at the code, sorry): Are they in
> |  the
> |  >>> same module? I.e., can GHC specialize the code to your particular
> |  Monad?
> |  >
> |  >> No, they're not in the same module. I could also try moving the
> |  >> zipWithAndUnzipM function to the same module, and even specializing
> |  >> it by hand to the right monad.
> |  >
> |  > I did mean zipWithAndUnzipM, so maybe yes: Try that.
> |  >
> |  > (I find it hard to believe that any polymorphic monadic code should
> |  > perform well

RE: performance regressions

2014-12-17 Thread Simon Peyton Jones
I still would like to understand why INLINE does not make it inline. That's 
weird.

Eg way to reproduce.

Simion

|  -Original Message-
|  From: Richard Eisenberg [mailto:e...@cis.upenn.edu]
|  Sent: 17 December 2014 15:56
|  To: Simon Peyton Jones
|  Cc: Joachim Breitner; ghc-devs@haskell.org
|  Subject: Re: performance regressions
|  
|  By unsubstantiated guess is that INLINEABLE would have the same effect
|  as INLINE here, as GHC doesn't see fit to actually inline the
|  function, even with INLINE -- the big improvement seen between (1) and
|  (2) is actually specialization, not inlining. The jump from (2) to (3)
|  is actual inlining. Thus, it seems that GHC's heuristics for inlining
|  aren't working out for the best here.
|  
|  I've pushed my changes, though I agree with Simon that more research
|  may uncover even more improvements here. I didn't focus on the number
|  of calls because that number didn't regress. Will look into this soon.
|  
|  Richard
|  
|  On Dec 17, 2014, at 4:15 AM, Simon Peyton Jones
|   wrote:
|  
|  > If you use INLINEABLE, that should make the function specialisable
|  to a particular monad, even if it's in a different module. You
|  shouldn't need INLINE for that.
|  >
|  > I don't understand the difference between cases (2) and (3).
|  >
|  > I am still suspicious of why there are so many calls to this one
|  function that it, alone, is allocating a significant proportion of
|  compilation of the entire run of GHC.  Are you sure there isn't an
|  algorithmic improvement to be had, to simply reduce the number of
|  calls?
|  >
|  > Simon
|  >
|  > |  -Original Message-
|  > |  From: ghc-devs [mailto:ghc-devs-boun...@haskell.org] On Behalf Of
|  > | Richard Eisenberg
|  > |  Sent: 16 December 2014 21:46
|  > |  To: Joachim Breitner
|  > |  Cc: ghc-devs@haskell.org
|  > |  Subject: Re: performance regressions
|  > |
|  > |  I've learned several very interesting things in this analysis.
|  > |
|  > |  - Inlining polymorphic methods is very important. Here are some
|  > | data  points to back up that claim:
|  > | * Original implementation using zipWithAndUnzipM:
|  8,472,613,440
|  > |  bytes allocated in the heap
|  > | * Adding {-# INLINE #-} to the definition thereof:
|  6,639,253,488
|  > |  bytes allocated in the heap
|  > | * Using `inline` at call site to force inlining:
|  6,281,539,792
|  > |  bytes allocated in the heap
|  > |
|  > |  The middle step above allowed GHC to specialize zipWithAndUnzipM
|  to
|  > | my  particular monad, but GHC didn't see fit to actually inline
|  the
|  > | function. Using `inline` forced it, to good effect. (I did not
|  > | collect  data on code sizes, but it wouldn't be hard to.)
|  > |
|  > |  By comparison:
|  > | * Hand-written recursion:6,587,809,112 bytes allocated in
|  the
|  > |  heap
|  > |  Interestingly, this is *not* the best result!
|  > |
|  > |  Conclusion: We should probably add INLINE pragmas to Util and
|  > | MonadUtils.
|  > |
|  > |
|  > |  - I then looked at rejiggering the algorithm to keep the common
|  > | case  fast. This had a side effect of changing the
|  zipWithAndUnzipM
|  > | to  mapAndUnzipM, from Control.Monad. To my surprise, this brought
|  > | disaster!
|  > | * Using `inline` and mapAndUnzipM:7,463,047,432 bytes
|  > |  allocated in the heap
|  > | * Hand-written recursion: 5,848,602,848 bytes
|  > |  allocated in the heap
|  > |
|  > |  That last number is better than the numbers above because of the
|  > | algorithm streamlining. But, the inadequacy of mapAndUnzipM
|  > | surprised  me -- it already has an INLINE pragma in Control.Monad
|  of course.
|  > |  Looking at -ddump-simpl, it seems that mapAndUnzipM was indeed
|  > | getting  inlined, but a call to `map` remained, perhaps causing
|  > | extra  allocation.
|  > |
|  > |  Conclusion: We should examine the implementation of mapAndUnzipM
|  > | (and  similar functions) in Control.Monad. Is it as fast as
|  possible?
|  > |
|  > |
|  > |
|  > |  In the end, I was unable to bring the allocation numbers down to
|  > | where  they were before my work. This is because the flattener now
|  > | deals in  roles. Most of its behavior is the same between nominal
|  > | and  representational roles, so it seems silly (though very
|  > | possible) to  specialize the code to nominal to keep that path
|  fast.
|  > | Instead, I  identified one key spot and made that go fast.
|  > |
|  > |  Thus, there is a 7% bump to memory usage on very-type-family-
|  heavy
|  > | code, compared to before my commit on Friday. (On more ordinary
|  > | code,  there is no noticeable change.)
|  > |
|  > |  Validating my patch locally now; will push when that's done.
|  > |
|  > |  Thanks,
|  > |  Richard
|  > |
|  > |  On Dec 16, 2014, at 10:41 AM, Joachim Breitner  | breitner.de> wrote:
|  > |
|  > |  > Hi,
|  > |  >
|  > |  >
|  > |  > Am Dienstag, den 16.12.2014, 09:59 -0500 schrieb Richard
|  E

RE: GHC Weekly News - 2014/12/16

2014-12-17 Thread Simon Peyton Jones
Austin, you may want to say when 7.8.4 will come out.

Simon

|  -Original Message-
|  From: ghc-devs [mailto:ghc-devs-boun...@haskell.org] On Behalf Of
|  Austin Seipp
|  Sent: 16 December 2014 21:11
|  To: ghc-devs@haskell.org
|  Subject: GHC Weekly News - 2014/12/16
|  
|  Hi *, time for another piece of the GHC weekly news!
|  
|- Joachim Breitner has gotten the new GHC 7.8.4 package to
|  tentatively build on ARM quite easily for Debian. Austin also took the
|  liberty of merging all the needed patches; they'll be part of the
|  7.8.4 release https://www.haskell.org/pipermail/ghc-devs/2014-
|  December/007608.html
|  
|- Greg Weber announced he's taken the time to set up a Docker image
|  for GHC development - if you're on Linux, Greg's image should help you
|  get up to speed with a GHC development environment in minutes!
|  https://www.haskell.org/pipermail/ghc-devs/2014-December/007606.html
|  
|- Lennart Kolmodin has spent time working on autocompletion for GHC,
|  and 7.10 will ship with bash completion scripts - which package
|  maintainers and distributions can now ship for their users. Thank you
|  Lennart! https://www.haskell.org/pipermail/ghc-devs/2014-
|  December/007614.html
|  
|- Adam Gundry has a question about the new type checker plugin
|  infrastructure; in particular - how do we deal with the serialization
|  of type checker evidence that plugins may want to create or pass
|  around on their own? Richard, Simon and Iavor weigh in.
|  https://www.haskell.org/pipermail/ghc-devs/2014-December/007626.html
|  
|- For the past few days, Richard Eisenberg has been hunting a
|  performance regression in the compiler. After profiling, discussion on
|  IRC and elsewhere, Richard has finally made some headway, and
|  discovered one of the 'hot spots' in his patch. Unfortunately the
|  battle isn't quite over just yet, and the hunt for a few more %
|  increase remains.
|  https://www.haskell.org/pipermail/ghc-devs/2014-December/007645.html
|  
|- David Spies has hit a very strange situation with GHC 7.8.3
|  running out of memory. But it turned out this was a change in 7.8, in
|  relation to how stacks were managed. Phew!
|  https://www.haskell.org/pipermail/ghc-devs/2014-December/007646.html
|  
|- Austin made a final call for 7.8.4 bugfixes. He plans on making
|  the final release this week, if nobody has any other major complaints.
|  https://www.haskell.org/pipermail/ghc-devs/2014-December/007684.html
|  
|  Finally, in a slight change, we'll also be covering some notes from
|  this week's meeting between GHC HQ (Austin, Simon PJ, SimonM, Herbert
|  and Mikolaj), including...
|  
|- The 7.10 RC1 looks like it's scheduled to occur this week still;
|  all of our libraries and submodules are up-to-date, and we've taken
|  the time to alert all of our maintainers about this. Thanks to Herbert
|  for taking control of this!
|  
|- We'll soon be implementing a new 'push hook' for the `ghc.git`
|  repository: no more trailing whitespace. Since we've recently
|  detabbed, and de-lhs-ified the tree, a knock-on effect was deleting
|  trailing whitespace. Now that we've done a lot of this, we should take
|  the time to enforce it - so they can't slip back in.
|  
|- Austin will be landing Phab:D169 and Phab:D396 soon to get it into
|  7.10.1 RC1.
|  
|- This week, Austin managed to secure two sponsors for
|  GHC/Haskell.org. We've been given a wonderful set of ARM buildbots
|  (running in the cloud!) and a new, incredibly powerful POWER8 machine
|  to use (with over 170 hardware threads available, for scalability
|  testing). Hooray for our friends at Online.net and RunAbove.com for
|  helping us out!
|  
|  Closed tickets this week include: #9871, #9808, #9870, #9605, #9874,
|  #9872, #9090, #9404, #8240, #9567, #9566, #9583, #9117, #9882, #9884,
|  #9372, #7942, #8951, #9817, #9620, #9336, #9523, #9552, #8988, #9390,
|  #9415, #9371, #7143, #9563, #8778, #4428, #4896, #9393, #9169, #7015,
|  #8943, #8621, #9132, #9857, #8024, #9831, and #9888.
|  
|  --
|  Regards,
|  
|  Austin Seipp, Haskell Consultant
|  Well-Typed LLP, http://www.well-typed.com/
|  ___
|  ghc-devs mailing list
|  ghc-devs@haskell.org
|  http://www.haskell.org/mailman/listinfo/ghc-devs
___
ghc-devs mailing list
ghc-devs@haskell.org
http://www.haskell.org/mailman/listinfo/ghc-devs


Re: performance regressions

2014-12-17 Thread John Lato
Is it possible INLINE didn't inline the function because it's recursive? If
it were my function, I'd probably try a manual worker /wrapper.

On 07:59, Wed, Dec 17, 2014 Simon Peyton Jones 
wrote:

> I still would like to understand why INLINE does not make it inline.
> That's weird.
>
> Eg way to reproduce.
>
> Simion
>
> |  -Original Message-
> |  From: Richard Eisenberg [mailto:e...@cis.upenn.edu]
> |  Sent: 17 December 2014 15:56
> |  To: Simon Peyton Jones
> |  Cc: Joachim Breitner; ghc-devs@haskell.org
> |  Subject: Re: performance regressions
> |
> |  By unsubstantiated guess is that INLINEABLE would have the same effect
> |  as INLINE here, as GHC doesn't see fit to actually inline the
> |  function, even with INLINE -- the big improvement seen between (1) and
> |  (2) is actually specialization, not inlining. The jump from (2) to (3)
> |  is actual inlining. Thus, it seems that GHC's heuristics for inlining
> |  aren't working out for the best here.
> |
> |  I've pushed my changes, though I agree with Simon that more research
> |  may uncover even more improvements here. I didn't focus on the number
> |  of calls because that number didn't regress. Will look into this soon.
> |
> |  Richard
> |
> |  On Dec 17, 2014, at 4:15 AM, Simon Peyton Jones
> |   wrote:
> |
> |  > If you use INLINEABLE, that should make the function specialisable
> |  to a particular monad, even if it's in a different module. You
> |  shouldn't need INLINE for that.
> |  >
> |  > I don't understand the difference between cases (2) and (3).
> |  >
> |  > I am still suspicious of why there are so many calls to this one
> |  function that it, alone, is allocating a significant proportion of
> |  compilation of the entire run of GHC.  Are you sure there isn't an
> |  algorithmic improvement to be had, to simply reduce the number of
> |  calls?
> |  >
> |  > Simon
> |  >
> |  > |  -Original Message-
> |  > |  From: ghc-devs [mailto:ghc-devs-boun...@haskell.org] On Behalf Of
> |  > | Richard Eisenberg
> |  > |  Sent: 16 December 2014 21:46
> |  > |  To: Joachim Breitner
> |  > |  Cc: ghc-devs@haskell.org
> |  > |  Subject: Re: performance regressions
> |  > |
> |  > |  I've learned several very interesting things in this analysis.
> |  > |
> |  > |  - Inlining polymorphic methods is very important. Here are some
> |  > | data  points to back up that claim:
> |  > | * Original implementation using zipWithAndUnzipM:
> |  8,472,613,440
> |  > |  bytes allocated in the heap
> |  > | * Adding {-# INLINE #-} to the definition thereof:
> |  6,639,253,488
> |  > |  bytes allocated in the heap
> |  > | * Using `inline` at call site to force inlining:
> |  6,281,539,792
> |  > |  bytes allocated in the heap
> |  > |
> |  > |  The middle step above allowed GHC to specialize zipWithAndUnzipM
> |  to
> |  > | my  particular monad, but GHC didn't see fit to actually inline
> |  the
> |  > | function. Using `inline` forced it, to good effect. (I did not
> |  > | collect  data on code sizes, but it wouldn't be hard to.)
> |  > |
> |  > |  By comparison:
> |  > | * Hand-written recursion:6,587,809,112 bytes allocated in
> |  the
> |  > |  heap
> |  > |  Interestingly, this is *not* the best result!
> |  > |
> |  > |  Conclusion: We should probably add INLINE pragmas to Util and
> |  > | MonadUtils.
> |  > |
> |  > |
> |  > |  - I then looked at rejiggering the algorithm to keep the common
> |  > | case  fast. This had a side effect of changing the
> |  zipWithAndUnzipM
> |  > | to  mapAndUnzipM, from Control.Monad. To my surprise, this brought
> |  > | disaster!
> |  > | * Using `inline` and mapAndUnzipM:7,463,047,432 bytes
> |  > |  allocated in the heap
> |  > | * Hand-written recursion: 5,848,602,848 bytes
> |  > |  allocated in the heap
> |  > |
> |  > |  That last number is better than the numbers above because of the
> |  > | algorithm streamlining. But, the inadequacy of mapAndUnzipM
> |  > | surprised  me -- it already has an INLINE pragma in Control.Monad
> |  of course.
> |  > |  Looking at -ddump-simpl, it seems that mapAndUnzipM was indeed
> |  > | getting  inlined, but a call to `map` remained, perhaps causing
> |  > | extra  allocation.
> |  > |
> |  > |  Conclusion: We should examine the implementation of mapAndUnzipM
> |  > | (and  similar functions) in Control.Monad. Is it as fast as
> |  possible?
> |  > |
> |  > |
> |  > |
> |  > |  In the end, I was unable to bring the allocation numbers down to
> |  > | where  they were before my work. This is because the flattener now
> |  > | deals in  roles. Most of its behavior is the same between nominal
> |  > | and  representational roles, so it seems silly (though very
> |  > | possible) to  specialize the code to nominal to keep that path
> |  fast.
> |  > | Instead, I  identified one key spot and made that go fast.
> |  > |
> |  > |  Thus, there is a 7% bump to memory usage on very-type-family-
> |  heavy
> |  > | cod

Re: performance regressions

2014-12-17 Thread Herbert Valerio Riedel
On 2014-12-16 at 22:45:36 +0100, Richard Eisenberg wrote:
> I've learned several very interesting things in this analysis.
>
> - Inlining polymorphic methods is very important. 

otoh, there are cases where marking methods INLINE have catastrophic
effects; the following

  
https://github.com/kolmodin/binary/commit/48c02966512a67b018fcdf093fab8d34bddf9a69

was necessary a few months ago, as otherwise GHC HEAD's compile-time
memory usage would explode:

  https://ghc.haskell.org/trac/ghc/ticket/9630

___
ghc-devs mailing list
ghc-devs@haskell.org
http://www.haskell.org/mailman/listinfo/ghc-devs


Understanding DsMeta module

2014-12-17 Thread Jan Stolarek
I'm implementing Template Haskell support for injective type families and I'm 
struggling to 
understand DsMeta module. It seems that all functions in that module delegate 
their calls to 
functions in Language.Haskell.TH.Lib via wired-in names and the `DsMeta.rep2` 
function. I'm 
puzzled by this design and I'd appreciate if someone could explain why things 
are done this way. 
Take this function example:

repPlainTV :: Core TH.Name -> DsM (Core TH.TyVarBndr)
repPlainTV (MkC nm) = rep2 plainTVName [nm]

where `plainTvName` is a name of `Language.Haskell.TH.Lib.plainTV`:

plainTV :: Name -> TyVarBndr
plainTV = PlainTV

Why not implement repPlainTV like this: ?

repPlainTV :: Core TH.Name -> DsM (Core TH.TyVarBndr)
repPlainTV (MkC nm) = return $ MkC (TH.PlainTV nm)

Janek
___
ghc-devs mailing list
ghc-devs@haskell.org
http://www.haskell.org/mailman/listinfo/ghc-devs


Re: Understanding DsMeta module

2014-12-17 Thread Richard Eisenberg

On Dec 17, 2014, at 12:29 PM, Jan Stolarek  wrote:
> 
> Why not implement repPlainTV like this: ?
> 
> repPlainTV :: Core TH.Name -> DsM (Core TH.TyVarBndr)
> repPlainTV (MkC nm) = return $ MkC (TH.PlainTV nm)
> 

In short, that's ill typed. We have

> newtype Core a = MkC CoreExpr

The idea behind this type is that its (phantom) type parameter tracks the type 
of the expression stored within. Of course, the thing within is always just a 
core expression. TH.PlainTV takes a TH.Name and produces a TH.TyVarBndr. But, 
nm is a CoreExpr and MkC is expecting a CoreExpr, so your suggestion wouldn't 
type check.

The higher-level answer is that you're mixing levels. The goal in DsMeta is 
*not* to create the TH AST. It's to create *core expressions* that create the 
TH AST.

Does this help?

Richard
___
ghc-devs mailing list
ghc-devs@haskell.org
http://www.haskell.org/mailman/listinfo/ghc-devs


Re: Understanding DsMeta module

2014-12-17 Thread Jan Stolarek
Thanks. That helps but I still don't understand why the calls are delegated to 
template-haskell 
library. Couldn't all of this be done locally?

Janek

Dnia środa, 17 grudnia 2014, Richard Eisenberg napisał:
> On Dec 17, 2014, at 12:29 PM, Jan Stolarek  wrote:
> > Why not implement repPlainTV like this: ?
> >
> > repPlainTV :: Core TH.Name -> DsM (Core TH.TyVarBndr)
> > repPlainTV (MkC nm) = return $ MkC (TH.PlainTV nm)
>
> In short, that's ill typed. We have
>
> > newtype Core a = MkC CoreExpr
>
> The idea behind this type is that its (phantom) type parameter tracks the
> type of the expression stored within. Of course, the thing within is always
> just a core expression. TH.PlainTV takes a TH.Name and produces a
> TH.TyVarBndr. But, nm is a CoreExpr and MkC is expecting a CoreExpr, so
> your suggestion wouldn't type check.
>
> The higher-level answer is that you're mixing levels. The goal in DsMeta is
> *not* to create the TH AST. It's to create *core expressions* that create
> the TH AST.
>
> Does this help?
>
> Richard


___
ghc-devs mailing list
ghc-devs@haskell.org
http://www.haskell.org/mailman/listinfo/ghc-devs


Re: Understanding DsMeta module

2014-12-17 Thread Richard Eisenberg
But you need an expression that, say, produces a PlainTV. Where are you going 
to find an expression that does this without using the template-haskell library?

On Dec 17, 2014, at 2:33 PM, Jan Stolarek  wrote:

> Thanks. That helps but I still don't understand why the calls are delegated 
> to template-haskell 
> library. Couldn't all of this be done locally?
> 
> Janek
> 
> Dnia środa, 17 grudnia 2014, Richard Eisenberg napisał:
>> On Dec 17, 2014, at 12:29 PM, Jan Stolarek  wrote:
>>> Why not implement repPlainTV like this: ?
>>> 
>>> repPlainTV :: Core TH.Name -> DsM (Core TH.TyVarBndr)
>>> repPlainTV (MkC nm) = return $ MkC (TH.PlainTV nm)
>> 
>> In short, that's ill typed. We have
>> 
>>> newtype Core a = MkC CoreExpr
>> 
>> The idea behind this type is that its (phantom) type parameter tracks the
>> type of the expression stored within. Of course, the thing within is always
>> just a core expression. TH.PlainTV takes a TH.Name and produces a
>> TH.TyVarBndr. But, nm is a CoreExpr and MkC is expecting a CoreExpr, so
>> your suggestion wouldn't type check.
>> 
>> The higher-level answer is that you're mixing levels. The goal in DsMeta is
>> *not* to create the TH AST. It's to create *core expressions* that create
>> the TH AST.
>> 
>> Does this help?
>> 
>> Richard
> 
> 
> 

___
ghc-devs mailing list
ghc-devs@haskell.org
http://www.haskell.org/mailman/listinfo/ghc-devs


Random holiday fun: Vote for buildbot naming conventions!

2014-12-17 Thread Austin Seipp
Hi *,

Everyone has been working hard getting things ready for the branch/RC
later this week - and that's really appreciated! As always, GHC
wouldn't be what it is without you.

But it's the holidays - that's stressful for some, and real time
consuming for others. So to keep things light and a little
interesting, and if you have a minute as an experiment, I'd like to
ask you all something:

What naming conventions should we use for GHC buildbots? We've been
adding more bots recently, and we've just gotten hold of some new
hardware this week.

Currently, GHC buildbots don't have any reserved name or identifier,
or DNS entries. I'd like to change that - we mostly refer to them by
IP, but this is annoying A) to remember and B) to tell other people.
We'll likely begin to lease out these machines to developers so they
can test and debug - meaning they'll be mentioned more.

I'd like to propose a theme for naming buildbots - this theme would be
used to populate DNS entries under the *.ghc.haskell.org domain.

The question is: what naming convention do we use?

So I created a poll for this. You can see that poll and vote for your
favorite options on Phabricator:

  - https://phabricator.haskell.org/V3

It's an approval vote rather than a plurality; so feel free to select
multiple choices. The winner with the most votes will get selected.

Note: the selection of options is relatively random and pre-selected;
there is an upper limit on the number of choices - 10 max - so I
merely picked some categories I thought would work and be generic
enough.

I imagine this vote will be open for about a week or so. I'd like it
if developers could vote on their favorites, or simply leave comments
on the vote for further suggestion - we could institute a vote with
better names.

Thanks all - and be sure to have happy holidays.

P.S I did not know RFC 1178 existed before today. Seems like there's
one for everything...

-- 
Regards,

Austin Seipp, Haskell Consultant
Well-Typed LLP, http://www.well-typed.com/
___
ghc-devs mailing list
ghc-devs@haskell.org
http://www.haskell.org/mailman/listinfo/ghc-devs


are patterns synonyms definable in GHCI?

2014-12-17 Thread Carter Schonwald
Hey all,
I was trying to define some pattern synonyms in ghci recently, and that
doesnt seem to work. Is that something slated to be fix in 7.10 or
something?
___
ghc-devs mailing list
ghc-devs@haskell.org
http://www.haskell.org/mailman/listinfo/ghc-devs