Programming Crystal Book Club

Ah hah! I found out Crystal has operators that allow wrapping with no exception throwing, you prepend & to things like + and so forth, so I updated the source to:

def fib(n)
    return n if n <= 1
    fib(n &- 1) &+ fib(n &- 2)
end

sum = 0

(1..42).each do |i|
    sum &+= fib(i)
end

puts sum

And compile and run!

❯ time shards build --release
Dependencies are satisfied
Building: crystal_fib
shards build --release  13.34s user 0.29s system 98% cpu 13.797 total

❯ time ./bin/crystal_fib 
701408732
./bin/crystal_fib  4.10s user 0.01s system 99% cpu 4.126 total

Hmm, I ran it a half dozen times and the same time result every time to within 0.01s, so it did help, but not as much as I’d hoped…

Taking a look at the assembly:

76385   │     .type   "*fib<Int32>:Int32",@function
76386   │ "*fib<Int32>:Int32":
76387   │ .Lfunc_begin239:
76388   │     .loc    7 1 0
76389   │     .cfi_startproc
76390   │     pushq   %rbp
76391   │     .cfi_def_cfa_offset 16
76392   │     pushq   %rbx
76393   │     .cfi_def_cfa_offset 24
76394   │     pushq   %rax
76395   │     .cfi_def_cfa_offset 32
76396   │     .cfi_offset %rbx, -24
76397   │     .cfi_offset %rbp, -16
76398   │     movl    %edi, %ebx
76399   │ .Ltmp10165:
76400   │     .loc    7 2 5 prologue_end
76401   │     cmpl    $1, %edi
76402   │     jg  .LBB239_3
76403   │     movl    %ebx, %eax
76404   │     .loc    7 0 0 is_stmt 0
76405   │     addq    $8, %rsp
76406   │     .cfi_def_cfa_offset 24
76407   │     popq    %rbx
76408   │     .cfi_def_cfa_offset 16
76409   │     popq    %rbp
76410   │     .cfi_def_cfa_offset 8
76411   │     retq
76412   │ .LBB239_3:
76413   │     .cfi_def_cfa_offset 32
76414   │     .loc    7 2 5
76415   │     leal    -1(%rbx), %edi
76416   │     .loc    7 3 5 is_stmt 1
76417   │     callq   "*fib<Int32>:Int32"
76418   │     movl    %eax, %ebp
76419   │     addl    $-2, %ebx
76420   │     .loc    7 3 20 is_stmt 0
76421   │     movl    %ebx, %edi
76422   │     callq   "*fib<Int32>:Int32"
76423   │     addl    %ebp, %eax
76424   │     .loc    7 0 0
76425   │     addq    $8, %rsp
76426   │     .cfi_def_cfa_offset 24
76427   │     popq    %rbx
76428   │     .cfi_def_cfa_offset 16
76429   │     popq    %rbp
76430   │     .cfi_def_cfa_offset 8
76431   │     retq
76432   │ .Ltmp10166:
76433   │ .Lfunc_end239:
76434   │     .size   "*fib<Int32>:Int32", .Lfunc_end239-"*fib<Int32>:Int32"
76435   │     .cfi_endproc

Well the test and jumps and exception are gone now, but it’s still generating very poor code, very weird…

Well, at least it’s faster than before, even if not as fast as any other native compiled language I’ve tested yet (even ocaml oddly)… ^.^;

2 Likes