Compile time woes

52 views
Skip to first unread message

Michael Snoyman

unread,
Feb 9, 2012, 7:09:32 AM2/9/12
to yeso...@googlegroups.com
Hi all,

We've started to get reports that with Persistent 0.8, compile times
for the Model file can be very large, sometimes non-terminating. I've
just spent a fair bit of time investigating, and as far as I can tell,
the problem is *not* coming from our TH code. When I turn on
-ddump-splices, all of the generated code is output almost
immediately. This implies very strongly to me that the problem is
coming from GHC itself. We've also discovered that playing around with
optimization options can drastically change results, which fits into
this theory pretty well. Unfortunately, I haven't been able to create
a reproducible test case separated out from a scaffolding, which leads
me to believe this is being triggered from a combination of many
issues.

So the question is: what can we do? I see a few options:

1. Fix GHC. This will be difficult and time consuming, but we should
definitely try to do it.
2. Figure out what changes went into Persistent 0.7/0.8 to trigger the
problem, and revert it. This is not really an optimal solution, since
we're tying out hands with what features we can implement.
3. Ditch TH entirely, and instead use code generation.

I'm actually very much in favor of (3). Even if we weren't running
into problems right now, I think we'd want to explore this possibility
anyway, since it can make it much easier to debug code. I've
considered this possibility in the past for Shakespeare as well, but
that would be much more invasive.

Since this bug has currently held up my development of another
project, I'm going to get working on (3) immediately. If anyone has
input on this, please let me know.

Meanwhile, I don't think we should let this issue hold up the 0.10
release. This change is very orthogonal to the Yesod library, and will
only affect the scaffolding.

Michael

Felipe Almeida Lessa

unread,
Feb 9, 2012, 7:20:52 AM2/9/12
to yeso...@googlegroups.com
On Thu, Feb 9, 2012 at 10:09 AM, Michael Snoyman <mic...@snoyman.com> wrote:
> We've started to get reports that with Persistent 0.8, compile times
> for the Model file can be very large, sometimes non-terminating.

What happens if you split TH code in on module Model.Entity and the
rest on Model.Rest? If that doesn't help, what if you add

{-# GHC_OPTIONS -O0 #-}

to one of these files?

I'd love to test this on our project but we're already carrying quite
a burden in terms of maintenance because of the
Yesod-0.10-which-is-not-0.10 situation, so I won't be able to test
this until The-Real-True-Yesod-0.10 gets released today =).

Regarding (3), I wouldn't like having another preprocessor unless it
had a clear advantage over TH code.

Cheers!

--
Felipe.

Michael Snoyman

unread,
Feb 9, 2012, 7:53:40 AM2/9/12
to yeso...@googlegroups.com
On Thu, Feb 9, 2012 at 2:20 PM, Felipe Almeida Lessa
<felipe...@gmail.com> wrote:
> On Thu, Feb 9, 2012 at 10:09 AM, Michael Snoyman <mic...@snoyman.com> wrote:
>> We've started to get reports that with Persistent 0.8, compile times
>> for the Model file can be very large, sometimes non-terminating.
>
> What happens if you split TH code in on module Model.Entity and the
> rest on Model.Rest?  If that doesn't help, what if you add
>
>  {-# GHC_OPTIONS -O0 #-}
>
> to one of these files?

No effect.

> I'd love to test this on our project but we're already carrying quite
> a burden in terms of maintenance because of the
> Yesod-0.10-which-is-not-0.10 situation, so I won't be able to test
> this until The-Real-True-Yesod-0.10 gets released today =).

I'm running the release scripts now. It should be available within the hour.

> Regarding (3), I wouldn't like having another preprocessor unless it
> had a clear advantage over TH code.

Well, the clear advantages of this approach would be:

* No performance issues
* Easy to inspect the generated code

The second point is why I've been wanting to do it for a while, the
first one is what's forcing my hand right now.

Michael

Felipe Almeida Lessa

unread,
Feb 9, 2012, 11:13:52 AM2/9/12
to yeso...@googlegroups.com
On Thu, Feb 9, 2012 at 10:53 AM, Michael Snoyman <mic...@snoyman.com> wrote:
> No effect.

This seems to do the trick:

{-# OPTIONS_GHC -O0 -fmax-simplifier-iterations=0 #-}

Only the file with the TH code needs this.

Cheers,

--
Felipe.

Felipe Almeida Lessa

unread,
Feb 9, 2012, 11:20:20 AM2/9/12
to yeso...@googlegroups.com

Sorry, but that doesn't work. For some reason, when linking I get

unknown symbol `persistentzm0zi8zi0_DatabaseziPersistziEntityDef_DBName_info'

However,

{-# OPTIONS_GHC -O0 -fmax-simplifier-iterations=1 #-}

seems to work. Not as fast as the broken option, but better than nothing =).

Cheers,

--
Felipe.

Michael Snoyman

unread,
Feb 9, 2012, 11:42:49 AM2/9/12
to yeso...@googlegroups.com
On Thu, Feb 9, 2012 at 6:20 PM, Felipe Almeida Lessa

Thank you! That seems to have let me build the file, though it was a
very long build. I still want to look into code generation as an
alternative to the TH, but at least there's no urgent need for it now.

Can anyone else who's been experiencing the long compile times confirm
that this helps the problem? If so, I think we should update the
scaffolding to include it.

Michael

Felipe Almeida Lessa

unread,
Feb 9, 2012, 11:55:36 AM2/9/12
to yeso...@googlegroups.com
On Thu, Feb 9, 2012 at 2:42 PM, Michael Snoyman <mic...@snoyman.com> wrote:
> Thank you! That seems to have let me build the file, though it was a
> very long build. I still want to look into code generation as an
> alternative to the TH, but at least there's no urgent need for it now.
>
> Can anyone else who's been experiencing the long compile times confirm
> that this helps the problem? If so, I think we should update the
> scaffolding to include it.

BTW, you may put "-v3" on the options to see which phase is slow.

Cheers,

--
Felipe.

Bardur Arantsson

unread,
Feb 9, 2012, 1:04:44 PM2/9/12
to yeso...@googlegroups.com
On 02/09/2012 01:09 PM, Michael Snoyman wrote:
> Hi all,
>
[--snip--]

> 3. Ditch TH entirely, and instead use code generation.
>
[--snip--]

> If anyone has input on this, please let me know.
>

Is there some reasonable way to incorporate a code generation step in
packages built by Cabal(-install)? I seem to recall trying to find one
and failing miserably.

(This was some time ago, so things may have changed -- hopefully for the
better.)

Regards,

Michael Snoyman

unread,
Feb 9, 2012, 4:19:49 PM2/9/12
to yeso...@googlegroups.com

There's some ability to have a code formatter (I don't remember the
exact term for it), which might be the approach we take. On the other
hand, we already have `yesod build` which is tied in to `yesod devel`,
so it might be sufficient to go down that route.

Michael

Bardur Arantsson

unread,
Feb 9, 2012, 4:36:10 PM2/9/12
to yeso...@googlegroups.com
On 02/09/2012 10:19 PM, Michael Snoyman wrote:
> On Thu, Feb 9, 2012 at 8:04 PM, Bardur Arantsson<sp...@scientician.net> wrote:
>> On 02/09/2012 01:09 PM, Michael Snoyman wrote:
>>>
>>> Hi all,
>>>
>> [--snip--]
>>
>>> 3. Ditch TH entirely, and instead use code generation.
>>>
>> [--snip--]
>>
>>> If anyone has input on this, please let me know.
>>>
>>
>> Is there some reasonable way to incorporate a code generation step in
>> packages built by Cabal(-install)? I seem to recall trying to find one and
>> failing miserably.
>>
>> (This was some time ago, so things may have changed -- hopefully for the
>> better.)
>>
>> Regards,
>>
>
> There's some ability to have a code formatter (I don't remember the
> exact term for it),

Ah, yes, I vaguely recall GHC having support for a pragma to specify a
preprocessor (I think that was the term) for the file -- this
preprocessor could of course transform the file to something completely
different (Haskell source). I wonder if that would work for Hackage,
though -- as I recall, the preprocessor had to be an existing binary on
the system.

Anyway, if you discover an elegant and simple way to get this working
with Hackage and cabal-install, I'd love a blog post detailing the
solution :).

Keep up the good work,

B�r�ur

Felipe Almeida Lessa

unread,
Feb 9, 2012, 7:36:08 PM2/9/12
to yeso...@googlegroups.com
BTW, Michael, did you try dumping the splices, pasting on a source
file and seeing if that helps the compilation times. I have feeling
that the compilation times are high not because of TH but because of
something else.

Cheers,

--
Felipe.

Michael Snoyman

unread,
Feb 10, 2012, 3:29:04 AM2/10/12
to yeso...@googlegroups.com

Unfortunately, the splices dumped by GHC are not properly formatted
Haskell code. I started doing what you mention, but it would take a
non-trivial amount of time to fix up the definitions spat out.

Michael

Bryan Richter

unread,
Feb 10, 2012, 11:04:00 AM2/10/12
to yeso...@googlegroups.com

(Aside)

Ok, I was wondering about that. I was looking at the splices generated
by Persist.Quasi and was worried that it was using language extensions
that would take me weeks to figure out...

Holger Reinhardt

unread,
Feb 10, 2012, 11:02:42 AM2/10/12
to Yesod Web Framework
I took a simple example and fixed the splice output: http://pastebin.com/ZuJn4P31
Compiling this with GHC 7.4.1 leads to OOM, compiling with 7.0.4 works
but takes a long time (in both cases using -O2).

I noticed that the migrateAll function (starting at line 972) seems
to be very inefficient. We call 'migrate' for every datatype in the
models file, but the first parameter of migrate (which is a
[EntityDef]) is always identical, only the second parameter varies.

So for testing purposes I abstracted out the first parameter of
'migrate' into a top-level definition and passed that into all calls
of migrate. And now the file compiles fine, though it still takes
about 40seconds.


On 10 Feb., 09:29, Michael Snoyman <mich...@snoyman.com> wrote:
> On Fri, Feb 10, 2012 at 2:36 AM, Felipe Almeida Lessa
>

Felipe Almeida Lessa

unread,
Feb 10, 2012, 11:33:56 AM2/10/12
to yeso...@googlegroups.com
On Fri, Feb 10, 2012 at 2:02 PM, Holger Reinhardt <hrein...@gmail.com> wrote:
> I took a simple example and fixed the splice output: http://pastebin.com/ZuJn4P31
> Compiling this with GHC 7.4.1 leads to OOM, compiling with 7.0.4 works
> but takes a long time (in both cases using -O2).

Thanks for your effort!

> I noticed that the migrateAll function  (starting at line 972) seems
> to be very inefficient. We call  'migrate' for every datatype in the
> models file, but the first parameter of migrate (which is a
> [EntityDef]) is always identical, only the second parameter varies.
>
> So for testing purposes I abstracted out the first parameter of
> 'migrate' into a top-level definition and passed that into all calls
> of migrate. And now the file compiles fine, though it still takes
> about 40seconds.

Looks like a low hanging fruit, so I'm going to fix it right now.

Thanks!

--
Felipe.

Felipe Almeida Lessa

unread,
Feb 10, 2012, 12:00:11 PM2/10/12
to yeso...@googlegroups.com

Fixed on git master [1]. It's now possible to compile persistent-test
with -O =).

Cheers,

[1] https://github.com/yesodweb/persistent/commit/fded3a6a896854e09af2f28ea5d6f5d8a5929ad3

--
Felipe.

Felipe Almeida Lessa

unread,
Feb 10, 2012, 12:15:54 PM2/10/12
to yeso...@googlegroups.com
On Fri, Feb 10, 2012 at 3:00 PM, Felipe Almeida Lessa
<felipe...@gmail.com> wrote:
> Fixed on git master [1].  It's now possible to compile persistent-test
> with -O =).

Actually, we can do even better on mkMigrate. Instead of repeating
all those boring definitions, now we just use "entityDef (undefined ::
Entity)" [2].

Cheers =), and sorry for the spam,

[2] https://github.com/yesodweb/persistent/commit/2ba16667d711bca821322cb60b24bb957f299ea7

--
Felipe.

Michael Snoyman

unread,
Feb 12, 2012, 8:32:28 AM2/12/12
to yeso...@googlegroups.com
On Fri, Feb 10, 2012 at 7:15 PM, Felipe Almeida Lessa

Wow, that makes things *much* better. Any reason not to upload this to Hackage?

Michael

Felipe Almeida Lessa

unread,
Feb 12, 2012, 9:01:00 AM2/12/12
to yeso...@googlegroups.com
On Sun, Feb 12, 2012 at 11:32 AM, Michael Snoyman <mic...@snoyman.com> wrote:
> Wow, that makes things *much* better. Any reason not to upload this to Hackage?

Yep: I forgot =).

Cheers,

--
Felipe.

Darrin Thompson

unread,
Feb 13, 2012, 12:41:05 PM2/13/12
to yeso...@googlegroups.com

For the slower kids who are still running yesod 0.10 from a week or so
ago? How, how, how do I get this?

--
Darrin

Holger Reinhardt

unread,
Feb 13, 2012, 12:49:02 PM2/13/12
to yeso...@googlegroups.com
> cabal install persistent-template-0.8.1.1
should work.

2012/2/13 Darrin Thompson <darr...@gmail.com>

Ilya Portnov

unread,
Feb 15, 2012, 12:31:27 PM2/15/12
to yeso...@googlegroups.com

On which version of GHC does it work? As for me, it compiles with GHC
7.2.1, but with 7.4.1 it gives something like

Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading package array-0.4.0.0 ... linking ... done.
Loading package deepseq-1.3.0.0 ... linking ... done.
Loading package old-locale-1.0.0.4 ... linking ... done.
Loading package time-1.4 ... linking ... done.
Loading package containers-0.4.2.1 ... linking ... done.
Loading package bytestring-0.9.2.1 ... linking ... done.
Loading package text-0.11.1.12 ... linking ... done.
Loading package attoparsec-0.10.1.1 ... linking ... done.
Loading package blaze-builder-0.3.1.0 ... linking ... done.
Loading package dlist-0.5 ... linking ... done.
Loading package hashable-1.1.2.3 ... linking ... done.
Loading package transformers-0.2.2.0 ... linking ... done.
Loading package mtl-2.0.1.0 ... linking ... done.
Loading package syb-0.3.6 ... linking ... done.
Loading package pretty-1.1.1.0 ... linking ... done.
Loading package template-haskell ... linking ... done.
Loading package unordered-containers-0.1.4.6 ... linking ... done.
Loading package primitive-0.4.1 ... linking ... done.
Loading package vector-0.9.1 ... linking ... done.
Loading package aeson-0.6.0.0 ... linking ... done.
Loading package base-unicode-symbols-0.2.2.3 ... linking ... done.
Loading package transformers-base-0.4.1 ... linking ... done.
Loading package monad-control-0.3.1 ... linking ... done.
Loading package base64-bytestring-0.1.1.0 ... linking ... done.
Loading package blaze-html-0.4.3.1 ... linking ... done.
Loading package lifted-base-0.1.0.3 ... linking ... done.
Loading package conduit-0.2.1 ... linking ... done.
Loading package path-pieces-0.1.0 ... linking ... done.
Loading package stm-2.2.0.1 ... linking ... done.
Loading package resource-pool-0.2.1.0 ... linking ... done.
Loading package pool-conduit-0.0.0.1 ... linking ... done.
Loading package persistent-0.8.0 ... linking ... done.
Loading package persistent-template-0.8.1.1 ... linking ... done.

and stops while eating about 100% CPU and 150Mb RAM.

Both 7.2.1 and 7.4.1 run on Debian amd64, but 7.2.1 is run on my desktop
(Debian testing/unstable, 4GB RAM), while 7.4.1 is run on relatively
clean VM (Debian testing, 1GB RAM).

WBR, Ilya Portnov.

Felipe Almeida Lessa

unread,
Feb 15, 2012, 11:46:11 AM2/15/12
to yeso...@googlegroups.com
On Wed, Feb 15, 2012 at 3:31 PM, Ilya Portnov <por...@iportnov.ru> wrote:
> and stops while eating about 100% CPU and 150Mb RAM.
>
> Both 7.2.1 and 7.4.1 run on Debian amd64, but 7.2.1 is run on my desktop
> (Debian testing/unstable, 4GB RAM), while 7.4.1 is run on relatively clean
> VM (Debian testing, 1GB RAM).
>
> WBR, Ilya Portnov.

The improvement should work on all GHC versions, but that doesn't mean
that it completely solves the problem.

Could you try putting

{-# OPTIONS_GHC -v3 #-}

as the first line on the offending file in order to see where GHC is
spending time?

Cheers,

--
Felipe.

Ilya Portnov

unread,
Feb 15, 2012, 1:05:36 PM2/15/12
to yeso...@googlegroups.com
15.02.2012 21:46, Felipe Almeida Lessa wrote:
> {-# OPTIONS_GHC -v3 #-}

http://paste.in.ua/3876/

and stops...

WBR, Ilya Portnov.

Felipe Almeida Lessa

unread,
Feb 15, 2012, 12:11:42 PM2/15/12
to yeso...@googlegroups.com
On Wed, Feb 15, 2012 at 4:05 PM, Ilya Portnov <por...@iportnov.ru> wrote:
> 15.02.2012 21:46, Felipe Almeida Lessa wrote:
>>
>> {-# OPTIONS_GHC -v3 #-}
>
>
> http://paste.in.ua/3876/
>
> and stops...

So it seems that GHC 7.4 is not behaving the same away as GHC 7.0. I
was seeing the simplifier taking quite some time. Also, -v3 seems to
show less output info, but I don't know which output level would be
better.

--
Felipe.

Ilya Portnov

unread,
Feb 15, 2012, 1:16:45 PM2/15/12
to yeso...@googlegroups.com
15.02.2012 22:11, Felipe Almeida Lessa пишет:

Yes, on other systems I've seen that simplification took much time with
same code. I think, here problem is in the simplification phase too.

WBR, Ilya Portnov.

Holger Reinhardt

unread,
Feb 15, 2012, 12:44:58 PM2/15/12
to yeso...@googlegroups.com
Can you post the contents of Types.hs and Entities.hs or is it confidential?

2012/2/15 Ilya Portnov <por...@iportnov.ru>

Ilya Portnov

unread,
Feb 15, 2012, 2:32:16 PM2/15/12
to yeso...@googlegroups.com
15.02.2012 22:44, Holger Reinhardt пишет:

> Can you post the contents of Types.hs and Entities.hs or is it confidential?
>

Types: http://paste.in.ua/3877/
Entities: http://paste.in.ua/3878/

WBR, Ilya Portnov.

Holger Reinhardt

unread,
Feb 15, 2012, 1:54:20 PM2/15/12
to yeso...@googlegroups.com
I tried it in:
- Windows 7 x64 + GHC 7.4.1
- Ubuntu 10.04 x64 + GHC 7.4.1 (running in Virtualbox)
In both cases it compiled fine. I also tried compiling with -O2 and that worked fine, too.

So I have no idea what the problem could be. You may want to try gradually removing stuff from the Entities.hs file and see if you can get it to compile.

2012/2/15 Ilya Portnov <por...@iportnov.ru>

Greg Weber

unread,
Feb 18, 2012, 10:15:46 AM2/18/12
to yeso...@googlegroups.com
There is a ticket open for this issue where the user still reports it on GHC 7.2
https://github.com/yesodweb/persistent/issues/47

Darrin Thompson

unread,
Feb 20, 2012, 12:50:48 PM2/20/12
to yeso...@googlegroups.com
On Sat, Feb 18, 2012 at 10:15 AM, Greg Weber <gr...@gregweber.info> wrote:
> There is a ticket open for this issue where the user still reports it on GHC 7.2
> https://github.com/yesodweb/persistent/issues/47
>

Is there a fix in the works for GHC and/or Persistent? Looks like I
upgraded to GHC 7.4.1 just in time to preserve the slowness. :-)

(addDependentFile is worth it though.)

--
Darrin

Reply all
Reply to author
Forward
0 new messages