20
votes

Haskell has many great tools for debugging run time performance issues, but what tools/rules of thumb exist for debugging compile time performance issues?

Specifically, the constraint solver in some of my code is taking forever (anywhere from 1-2 seconds to several minutes). I'm pretty sure this is due to how I'm using type families in the constraints, but I have no idea what sort of things are expensive in this context or how to see where the constraint solver is spending its time. My best guess is that one of my operations on type lists is taking quadratic time instead of linear.

Let's see an example of why I suspect the constraint solver. In my files, I have code that looks like:

class ExampleClass a where
    type ExampleType a
    f :: ExampleType a -> a

data ExampleData (xs :: [a]) = ...

instance 
    ( Constraint1
    , Constraint2
    , ...
    ) => ExampleClass (ExampleData xs) 
        where
    type ExampleType (ExampleData xs) = Int
    f = undefined

When I load this file into ghci

ghci> :l Example.hs

compilation happens very quickly, much less than 1 second. Then, I execute the following line:

ghci> let test = f Int :: ExampleData

No actual computation is going on, but this still takes a very long time. The more constraints in ExampleData's instance declaration, the longer it takes. (Actually evaluating test later happens instantly.) The best way I've figured out how to debug these performance issues is by commenting out constraints one-by-one and seeing which ones are causing the performance hit. But this is very time consuming, and when those constraints involve complex type families, it's not really all that informative.

So, is there a better approach I can take to debug this problem?


Edit: It turns out I discovered a bug in GHC. There's a script associated with the bug that demonstrates that the constraint solver is taking quadratic time on inputs that should be linear.

1
I assume you've tried compiling GHC with profiling turned on and using that?Boyd Stephen Smith Jr.
@BoydStephenSmithJr. I've never compiled GHC before, let alone with compiling turned on. Is there a tutorial on how to use this feature?Mike Izbicki
Building GHC is probably a good resource, and there's a even section on benchmarking GHC though I don't know if it includes profiling.Boyd Stephen Smith Jr.

1 Answers

7
votes

For what it's worth, you can evaluate constraints one at a time using :kind! to see how long it takes, instead of needing to comment them out individually.