#4 make-instance
ちゃんと profile とかしてないんだが、どうも generic-function の呼び出しがネックな気がする。
(make-instance 'foo :key <value>)
が
;;; 0 (defmethod make-instance ((class symbol) &rest initargs) (apply #'make-instance (find-class class) initargs)) ; 1へ ;;; 1 (defmethod make-instance ((class standard-class) &rest initargs) (let ((instance (allocate-instance class))) ; 2へ (apply #'initialize-instance instance initargs) ;3から4へ instance)) ;;; 2 (defmethod allocate-instance ((class standard-class)) (std-allocate-instance class)) ;;; 3 (defmethod initialize-instance ((instance standard-object) &rest initargs) (apply #'shared-initialize instance t initargs)) ;;; 4 (defmethod shared-initialize ((instance standard-object) slot-name &rest all-keys) (dolist (slot (class-slots (class-of instance))) ...))
とあちこちパス回しされてたので
(defmethod make-instance ((class standard-class) &rest initargs) (let ((instance (std-allocate-instance class))) (apply #'shared-initialize instance t initargs) instance))
とスルーパスにしたら 10% くらい速くなった。
余談:
closette.l の file-write-time を監視して update されたらベンチする関数を timer で動かしっぱなし。
(let ((last-update (file-write-time *closette-file*)) (buff (get-buffer-create "*Results*"))) (defun bench () (let ((update (file-write-time *closette-file*))) (when (> update last-update) (setq last-update update) (load-file *closette-file*) (closette::bootstrap) (defclass foo () ((data :accessor foo-data :initarg :data))) (message "benchmarking...") (let ((result (time (let ((list nil)) (dotimes (n 500) (push (make-instance 'foo :data (random 1000)) list)) (sort list #'< :key #'foo-data))))) (message "benchmarking...done in ~S sec." result) (format (make-buffer-stream buff) "~A: ~S sec~%" (format-date-string *w3c-dtf* update) result) (refresh-screen))))))
これが4秒くらいかかってる。structure だと0.03秒くらい。