時間を計る
今,scratch buffer をヴァージョン管理するという誰得な拡張を作っているんですが,その一部に汎用化できそうな部分があったんで,抜き出してご紹介.
stopwatch.el
Features
以下の関数を使って時間を比較できるようになります.扱える時間のフォーマットは (high low microsec),または (high low) です.
stopwatch (time1 &optional time2)
TIME1 と TIME2 の差分を計算します.返り値は high low microsec をつなぎあわせた数字になります.TIME2 を省略した場合は current-time() との比較になります.
stopwatch-by-UNIT (time1 &optional time2 integer)
stopwatch() と同様に差分を計算しますが,返り値は UNIT で表される単位に変換された値(小数)です.INTEGER が non-nil の場合,結果は整数(小数点以下切り捨て)になります.UNIT にはデフォルトで小さい方から ms, sec, min, hour, day が当てはまります.マクロ stopwatch-define-unit-fn() を使って関数を自分で定義することもできます.
また,時間をメッセージで出力するマクロも定義しています.
with-stopwatch (message &rest body)
BODY を囲む形で使います.MESSAGE は文字列,あるいは文字列を返す式です.メッセージを表示しながら BODY を評価し,最後にかかった時間をミリ秒で表示します.返り値は BODY の返り値と同じになります.
Usage
これだけじゃ何が便利だかわからないと思うので,いくつか例を.
- Emacsの起動にかかった時間をミリ秒で出す.
(stopwatch-by-ms before-init-time after-init-time) ; => 1613.221
- Emacsを起動させてからの経過時間を分で出す.
(stopwatch-by-min after-init-time nil t) ; => 13
- ファイル hoge の最終更新時刻から現在までの日数を出す.
(stopwatch-by-day (nth 5 (file-attributes hoge))) nil t) ; => 291
- 時間表示付きの簡単なデバッグを行う.
Emacs Lisp を編集しているときにちょっとしたデバッグのために,式と式の間に message() を仕込んだりすることがあります.それと同様のことを時間表示付きで行うことが出来ます.
;; auto-complete.el 内の ac-symbol-candidates() の定義より抜粋. (or ac-symbols-cache (setq ac-symbols-cache ;; loop について調査 (with-stopwatch "TEST: loop for ac-symbols-cache" (loop for x being the symbols if (or (fboundp x) (boundp x) (symbol-plist x)) collect (symbol-name x)))))
上の式を評価すると,*Messages* buffer に返り値と共に次のように表示され,loop 処理が中断なく実行されていることと,おおよその実行時間がわかります.
Running TEST: loop for ac-symbols-cache...done [36.923 ms] ("yas/check-commit-snippet" "yas/use-menu" "find-library-name" "Buffer-menu" "menu-bar-update-buffers" "vc-mtn-admin-dir" "desktop-clear" "egg-status-popup-delta-menu" "ac-l-prefix-in-paren" "popup-menu-show-quick-help" "auto-install-emacswiki-base-url" "mm-ucs-to-char" ...)
更新情報
version 0.2: stopwatch-define-unit-fn を定義.関数の使い方を統一.