Emacs24のelispは速いぞ!ベンチマークを測定してみた

Emacs24「ねんがんのlexical-bindingをてにいれたぞ!」

10年にわたって開発してきたlexical-bindingがついにEmacs24に取り込まれました。

これはEmacs界の大大大ニュースです!

lexical-bindingが有効になると、letがlexical-letに化けます。

lexical-bindingは速いということらしいのですが、現時点でベンチマークをみかけないので測定してみました。

lexical-bindingは変数lexical-bindingをtにすると有効になります。
この変数は、バッファローカル変数なのでsetqで設定しても他のバッファに影響はありません。

M-x ielmで実験してみましょう。

ELISP> (setq lexical-binding t)
t
ELISP> (defun f1 (n) (let ((i 1) (s 0)) (while (<= i n) (setq s (+ s i)) (setq i (1+ i))) s))
f1
ELISP> (f1 10)
55
ELISP> (byte-compile 'f1)
nil
ELISP> (symbol-function 'f1)
(closure
 (t)
 (n)
 (let
     ((i 1)
      (s 0))
   (while
       (<= i n)
     (setq s
           (+ s i))
     (setq i
           (1+ i)))
   s))

ぬ、lexical-bindingを設定したらielmではバイトコンパイルできないぞ??

とりあえず、適当なファイルを開いて以下の内容にして、C-u M-x byte-compile-file。

lexical-bindingをファイル内で有効にするには、こんなふうに一行目に -*- lexical-binding: t -*- を入れること。

;; -*- lexical-binding: t -*-
(defun f1 (n) (let ((i 1) (s 0)) (while (<= i n) (setq s (+ s i)) (setq i (1+ i))) s))


そこでM-x rename-uniquelyでバッファ名を変えて、再びM-x ielm。
こっちはlexical-bindingを使わない方。

ELISP> (defun f2 (n) (let ((i 1) (s 0)) (while (<= i n) (setq s (+ s i)) (setq i (1+ i))) s))
f2
ELISP> (byte-compile 'f2)
#[(n)
  略(バイトコード)
  [s i n 1 0]
  3]

さっそく測定。

ELISP> (benchmark-run 1 (f1 100000))
(0.016059 0 0.0)
ELISP> (benchmark-run 1 (f2 100000))
(0.022624 0 0.0)

lexical-bindingによって3割ほど高速化しました。

P.S.

Emacsのネット塾を運営しています。
最新の技術を数分で自分のものにすることができます。
ここで一気にライバルに差をつけてしまいましょう。