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

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

当我将这个文件加载到ghci中

ghci> :l Example.hs

编译发生得非常快,远不到1秒。 然后,我执行以下行:

ghci> let test = f Int :: ExampleData

没有实际的计算正在进行,但这仍然需要很长时间。 ExampleData的实例声明中的约束越多,需要的时间就越长。 (实际上后来评估测试会立即发生。)我已经想出了如何调试这些性能问题的最佳方式是逐个评论约束条件并查看哪些导致性能下降。 但是这非常耗时,而当这些限制涉及复杂类型的家庭时,并不是所有的信息都是如此。

那么,有没有更好的方法可以调试这个问题?


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


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

链接地址: http://www.djcxy.com/p/33207.html

上一篇: Debugging compile time performance issues caused by GHC's constraint solver

下一篇: Haskell: Where vs. Let