#簡単なプログラムでベンチマークを取ってみたのですが、Gaucheではローカル手続きで末尾再帰にするのが一番効率的なんですか?
#@yosaka 何と比較したかによりますが、ローカル手続きの末尾再帰だと大抵はループにコンパイルされるので速くなることが多いでしょうね。
#グローバル手続きへの末尾再帰だと、一応その手続きの呼び出しインストラクションが入ります。ループ中にそのグローバル手続きが再定義される可能性があるので。
#今回ベンチマークを取ったのは、1..1000000までのリストで10000以下をリストにして返すというプログラムです。fold,fold-right,filter,take,named let,internal definede比較してみて、internal defineが一番速かったので
#もしかしたら、ローカル手続きの末尾再帰が一番効率的なのかなと思い質問しました。
#ああなるほど。そのくらいだと手続き呼び出しの時間が支配的になると思うので、全く手続き呼び出しが発生しないinternal defineが速くなりそうですね。named letも構文糖衣なだけでinternal defineと同じにならないかな? disasmしてみると手続き呼び出しがどうなってるかわかると思います。
#ベンチマーク結果は
#;(time (fold-right (lambda (x y) (cond ((> 10000 x) (cons x y)) (else y) ...
; real 0.662
; user 0.610
; sys 0.050
;(time (fold (lambda (x y) (cond ((> 10000 x) (cons x y)) (else y))) '() ...
; real 0.219
; user 0.200
; sys 0.020
;(time (filter (lambda (x) (> 10000 x)) (iota 1000000)))
; real 0.222
; user 0.220
; sys 0.000
;(time (take (iota 1000000) 10000))
; real 0.143
; user 0.140
; sys 0.000
;(time (let loop ((init '()) (lis (iota 1000000 1))) (cond ((null? lis) ...
; real 0.102
; user 0.110
; sys 0.000
;(time (loop (iota 1000000 1)))
; real 0.100
; user 0.100
; sys 0.000
#です。
#ほとんどnamed letとinternal defineはほとんど同じですね。
#shiroさん、質問に答えて頂きありがとうございました。
#久しぶりに実家に行って、20kg超の姪っ子を肩車して2km先の公園まで歩いた
#トレーニング再開の一歩にはヘヴィすぎ