Hatena::Groupcadr

わだばLisperになる このページをアンテナに追加 RSSフィード

2004 | 12 |
2005 | 01 | 02 | 07 | 10 | 11 |
2006 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 11 |

2009-11-28

KMRCLを眺める (24) time-iterations

| 01:30 | KMRCLを眺める (24) time-iterations - わだばLisperになる を含むブックマーク はてなブックマーク - KMRCLを眺める (24) time-iterations - わだばLisperになる

今日は、KMRCLのmacros.lispの中からTIME-ITERATIONSです。

TIME-ITERATIONSは、ボディ部が任意の回数繰り返されるTIMEマクロ、というところで

定義は、こんな感じです。

(defmacro time-iterations (n &body body)
  (let ((i (gensym))
        (count (gensym)))
    `(progn
       (let ((,count ,n))
         (format t "~&Test with ~d iterations: ~W" ,count (quote ,body))
         (let ((t1 (get-internal-real-time)))
           (dotimes (,i ,count)
             ,@body)
           (let* ((t2 (get-internal-real-time))
                  (secs (coerce (/ (- t2 t1)
                                   internal-time-units-per-second)
                                'double-float)))
             (format t "~&Total time: ")
             (print-seconds secs)
             (format t ", time per iteration: ")
             (print-seconds (coerce (/ secs ,n) 'double-float))))))))

使い方は、

(TIME-ITERATIONS 10
  (DOTIMES (I 1000000)
    (+ 1 1)))
Test with 10 iterations: ((DOTIMES (I 1000000) (+ 1 1)))
Total time: 10.61 sec, time per iteration: 1.06 sec
;⇒ NIL

(TIME-ITERATIONS 10
  (DOTIMES (I 1000000)
    (eval '(+ 1 1))))
Test with 10 iterations: ((DOTIMES (I 1000000) (EVAL '(+ 1 1))))
Total time: 15.55 sec, time per iteration: 1.56 sec
;⇒ NIL

という感じでしょうか。

こういうユーティリティをみるとslimeと連携させてみたくなるのですが、いつもの雛形をちょっといじって

;; Emacs lisp
(eval-after-load "slime"
  '(progn
     (defun slime-time-iterations (times)
       (interactive "p")
       (slime-eval-and-time-iterations
        `(swank:eval-and-grab-output
          ,(format "(kmrcl:time-iterations %s %s)" 
                   times
                   (slime-defun-at-point)))))
     
     (defun slime-eval-and-time-iterations (form)
       (slime-eval-async form (slime-rcurry #'slime-show-time-iterations
                                            (slime-current-package))))
     
     (defun slime-show-time-iterations (string package)
       (slime-with-popup-buffer ("*SLIME TIME-ITERATIONS*" package t t)
         (lisp-mode)
         (princ (first string))
         (goto-char (point-min))))
     
     ;; SUPER-SHIFT-T
     (define-key slime-mode-map
       [(super shift ?t)] 'slime-time-iterations)))

というのを作ってみました。

任意の式の上で、C-u 10 Super-Shift-Tすると、別バッファに10回繰り返された結果が表示されるのですが、あまり便利でもありません…。

ちなみに、このパターンはslimeを拡張するときに自分内では頻出するのでEmacs lispでマクロを書きたいところです。