[PR]今日のニュースは
「Infoseek モバイル」


xyzzy メモ


2007/08/04(Sat) 21:11

最適化メモ。

関数をバイトコンパイル時に最適化するには、シンボルに compiler::optimize-form 属性を設定する。マクロを書く要領で optimizer を与えるとコンパイル前にフォームが optimizer に渡され、戻り値がコンパイルされる。バイトコードを直接いじることはたぶんできない。

例。まずはテスト用の関数を定義。

(defun add (x y) (+ x y))

(defun test1 () (dotimes (_ 100000) (add 1 1)))

(defun test2 () (dotimes (_ 100000) (+ 1 1)))

(time (test1))
=> 5079

(time (test2))
=> 4687

time は実行時間(ms)を計測するマクロ。あらかじめ適当に定義しておく。コンパイルしなければこんなものか。

(progn (compile 'test1) (compile 'test2))

(time (test1))
=> 532

(time (test2))
=> 16

コンパイルしたらはっきりと差が出た。add をインライン展開してみる。

(setf (get 'add 'compiler::optimize-form) #'(lambda (x) `(+ ,@(cdr x))))
(defun test1 () (dotimes (_ 100000) (add 1 1)))
(compile 'test1)
(time (test1))
=> 16

めでたく test2 と同じ実行時間に。


2007/05/16(Wed) 21:07

macroexpand-all が間違っていたことに今更ながら気付いたので直してみた。やっぱりいろいろいい加減。

(defun macroexpand-all (x)
  (if (atom x) (return-from macroexpand-all x))
  (setq x (macroexpand x))
  (case (car x)
    ((interactive save-restriction save-excursion save-window-excursion
       si:*byte-code unwind-protect progn tagbody if block catch
       multiple-value-call multiple-value-prog1 setq)
     (list* (car x) (mapcar 'macroexpand-all (cdr x))))
    ((let let*)
     (list* (car x)
            (mapcar (lambda (b)
                      (if (atom b) b
                        (list (car b) (macroexpand-all (cadr b)))))
                    (cadr x))
            (mapcar 'macroexpand-all (cddr x))))
    ((macrolet flet labels)
     (list* (car x)
            (mapcar (lambda (b)
                      (list* (car b) (cadr b)
                             (mapcar 'macroexpand-all (cddr b))))
                    (cadr x))
            (mapcar 'macroexpand-all (cddr x))))
    ((throw return-from)
     (if (cddr x)
         (list (car x) (cadr x)
               (macroexpand-all (caddr x)))
       x))
    ((multiple-value-setq)
     (list 'multiple-value-setq (cadr x) (macroexpand-all (caddr x))))
    ((multiple-value-bind eval-when)
     (cons (car x) (mapcar 'macroexpand-all (cdr x))))
    ((function quote go)
     x)
    (t
     (cons (car x) (mapcar 'macroexpand-all (cdr x))))))

2007/01/24(Wed) 22:49

macroexpand-all を書いてみた。かなり投げやりな感じがしなくもないが、たぶんこれでいいと思う。

(defun macroexpand-all (x)
  (if (atom x) (return-from macroexpand-all x))
  (setq x (macroexpand x))
  (cons (car x) (mapcar 'macroexpand-all (cdr x))))

トップへ