ソートのパフォーマンスチューニング

 以下のsort1とsort2はパフォーマンスが2倍以上も違う。この速度差はどこから来るのか。

(use gauche.time)

(define-class  () *1

(define l '())
(define i 0)

(while (< i 30000)
    (set! l (list* 1 2 3 4 5 6 7 8 9 0 l))
  (inc! i))

(define (cmp a b c)
  (if (< a b)
      #t #f))

(define (sort1 seq x)
  (sort seq (lambda (a b)
	      (cmp a b (ref x 'p)))))

(define (sort2 seq x)
  (let1 xp (ref x 'p)
    (sort seq (lambda (a b)
		(cmp a b xp)))))

(time (sort1 l dummy))
(time (sort2 l dummy))

 sort1とsort2で違うところは先に(ref x 'p)の結果をxpに束縛しているかどうかだけだが、この差が劇的な効果をもたらす。考えてみれば当たり前の話で、sort1は比較関数を呼ぶたびに(ref x 'p)を実行している。比較関数はなんだかすごい何回も呼ばれるので、その中で無駄な呼出しをしていると遅くなるわけだ。
 考えてみたら当たり前の話のような気がするんだけど、今日はここではまってなかなかチューニングがうまくいかなかったのでメモしておく。

*1:p :init-value 0))) (define dummy (make