详尽的Haskell模式匹配的性能

时间:2018-02-01 21:58:17

标签: performance haskell pattern-matching

我想知道如何在内部解决Haskell模式匹配以及它如何影响性能。假设我们有一个计算成本很高的函数,所以我们在进行实际计算之前预先计算相应输入上的第一个和/或更常用的值和模式匹配:

expensiveComputation :: Int -> Int
expensiveComputation 1 = 101
expensiveComputation 2 = 3333333
expensiveComputation 3 = 42
...
expensiveComputation n = the actual function

如果我们想要的话,我们可以预先计算很多这些案例,但是我们呢?我假设Haskell实际上找到匹配输入的模式需要时间,所以也许它实际上更快计算第1000个值而不是1000个模式匹配?

1 个答案:

答案 0 :(得分:14)

我在表格中做了一个简单的测试:

ghc -O2 -ddump-asm -c

使用_c2aD: movl $28,%ebx ; N.B. the constant 28 matches my largest value jmp *(%rbp) _c2aC: movl $27,%ebx jmp *(%rbp) _c2aB: movl $26,%ebx jmp *(%rbp) .... 编译。我观察了关键的ASM:

每个顶级等式似乎都是实现的:

_n2aN:
        .quad   _c2af-(_n2aN)+0
        .quad   _c2ag-(_n2aN)+0
        .quad   _c2ah-(_n2aN)+0
        .quad   _c2ai-(_n2aN)+0
        .quad   _c2aj-(_n2aN)+0
        .quad   _c2ak-(_n2aN)+0
        ...

什么似乎是参考上述实现的跳转表:

_c2aE:
        cmpq $25,%r14        ; N.B. the last defined input is 24
        jge _c2ae
_u2aH:
        testq %r14,%r14
        jl _c2ae
_u2aI:
        leaq _n2aN(%rip),%rax
        addq (%rax,%r14,8),%rax
        jmp *%rax

看起来似乎是一对护卫员随后发送:

first = i + 1

那么我认为1000条目的速度会慢吗?不,如果它们是连续的,我敢打赌GHC将生成一个跳转表,就像我在这里看到的一样。另一个有趣的测试是它们是不是连续的。