[Haskell-beginners] Function definition order and performance

Aleksandar Dimitrov aleks.dimitrov at googlemail.com
Tue Jun 7 10:33:08 CEST 2011


> I have not met a performance issue yet. Thanks. I'm just a beginner.
> I was just wondering how they will be different. For instance,
> 
> safeHead [] = Nothing
> safeHead (x : xs) = Just x
> 
> vesus
> 
> safeHead (x : xs) = Just x
> safeHead [] = Nothing

There is no difference in this case. GHC compiles that down to the very same
thing.

Given this file:


> safeHead [] = Nothing
> safeHead (x:xs) = Just x
> 
> safeHead' (x:xs) = Just x
> safeHead' [] = Nothing

You can look at the ghc core (the intermediate compiler output produced by GHC)
to find out what the difference is. Core is basically like machine-generated
Haskell with some syntactical oddities. Don Steward's ghc-core program on
hackage displays core nicely.

Here are the relevant core blocks:

> safeHead' =
>   \ (@ a_acw) (ds_dcU :: [a_acw]) ->
>     case ds_dcU of _ {
>       [] -> Data.Maybe.Nothing @ a_acw;
>       : x_abJ xs_abK -> Data.Maybe.Just @ a_acw x_abJ
>     }

> safeHead =
>   \ (@ a_acy) (ds_dcX :: [a_acy]) ->
>     case ds_dcX of _ {
>       [] -> Data.Maybe.Nothing @ a_acy;
>       : x_abx xs_aby -> Data.Maybe.Just @ a_acy x_abx
>     }

And, well, they're exactly the same (sans a few differences in variable naming,
which have no impact whatsoever.) Your pattern match gets compiled down to a
case pattern match, and the arguments are re-ordered. While you *can* look at
the assembly, from here on out, it doesn't make sense, because GHC uses Core as
a basis for compilation, *not* your code (it does your code as a basis for
Core.)

For completion's sake, the assembly, which is unexcitingly identical in both
cases, is below. Note that the only thing interesting here is that safeHead' got
translated to safeHeadzq, which is… well. Cute, and nothing else.

Really though, if you're still at RWH, chapter three, it's Ok to be interested
in these kinds of subtle performance differences, but you shouldn't concentrate
on them.
At this point, you can trust the compiler to optimize your code enough, and you
can worry about performance if your program is actually slow.

Happy Haskell hacking :-)
Aleks

Main_safeHeadzq_closure:
        .quad  Main_safeHeadzq_info
.text
        .align 8
        .quad  0
        .quad  32
se2_info:
.Lcek:
        movq %rbx,%rax
        andq $7,%rax
        cmpq $2,%rax
        jae .Lcel
        movl $base_DataziMaybe_Nothing_closure+1,%ebx
        addq $8,%rbp
        jmp *0(%rbp)
.Lcel:
        addq $16,%r12
        cmpq 144(%r13),%r12
        ja .Lces
        movq $base_DataziMaybe_Just_con_info,-8(%r12)
        movq 6(%rbx),%rax
        movq %rax,0(%r12)
        leaq -6(%r12),%rbx
        addq $8,%rbp
        jmp *0(%rbp)
.Lces:
        movq $16,184(%r13)
.Lceq:
        jmp *-16(%r13)
.text
        .align 8
        .quad  4294967301
        .quad  0
        .quad  15

Main_safeHead_closure:
        .quad  Main_safeHead_info
.text
        .align 8
        .quad  0
        .quad  32
seJ_info:
.Lcf1:
        movq %rbx,%rax
        andq $7,%rax
        cmpq $2,%rax
        jae .Lcf2
        movl $base_DataziMaybe_Nothing_closure+1,%ebx
        addq $8,%rbp
        jmp *0(%rbp)
.Lcf2:
        addq $16,%r12
        cmpq 144(%r13),%r12
        ja .Lcf9
        movq $base_DataziMaybe_Just_con_info,-8(%r12)
        movq 6(%rbx),%rax
        movq %rax,0(%r12)
        leaq -6(%r12),%rbx
        addq $8,%rbp
        jmp *0(%rbp)
.Lcf9:
        movq $16,184(%r13)
.Lcf7:
        jmp *-16(%r13)
.text
        .align 8
        .quad  4294967301
        .quad  0
        .quad  15

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 490 bytes
Desc: Digital signature
URL: <http://www.haskell.org/pipermail/beginners/attachments/20110607/3e0bf923/attachment.pgp>


More information about the Beginners mailing list