调试由GHC的约束求解器引起的编译时性能问题

Mik*_*cki 20 debugging performance haskell ghc type-constraints

Haskell有许多用于调试运行时性能问题的好工具,但是有哪些工具/经验法则可用于调试编译时性能问题?

具体来说,我的一些代码中的约束求解器将永远占用(从1-2秒到几分钟).我很确定这是由于我在约束中如何使用类型族,但我不知道在这种情况下哪种东西是昂贵的,或者如何看待约束求解器花费时间的位置.我最好的猜测是我对类型列表的操作之一是采用二次时间而不是线性时间.

让我们看一个为什么我怀疑约束求解器的例子.在我的文件中,我的代码如下:

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
Run Code Online (Sandbox Code Playgroud)

当我将此文件加载到ghci中时

ghci> :l Example.hs
Run Code Online (Sandbox Code Playgroud)

编译很快发生,远不到1秒.然后,我执行以下行:

ghci> let test = f Int :: ExampleData
Run Code Online (Sandbox Code Playgroud)

没有实际的计算,但这仍然需要很长时间.ExampleData实例声明中的约束越多,所需的时间就越长.(实际上后来评估测试会立即发生.)我弄清楚如何调试这些性能问题的最好方法是逐个注释掉约束并查看哪些因素导致了性能损失.但这是非常耗时的,当这些限制涉及复杂类型的家庭时,它并不是真正的信息.

那么,我可以采用更好的方法来调试这个问题吗?


编辑:事实证明我发现了GHC中的一个错误.有一个与该bug相关联的脚本,表明约束求解器在输入上采用二次时间应该是线性的.

小智 7

对于它的价值,您可以使用以下方法一次评估约束:亲切!看看需要多长时间,而不是需要单独评论它们.