勝利の鍵はwrite-string

*前回のあらすじ*
文字列を一回なぞって単純な置換をするだけのプログラムの速度が
正規表現エンジンCL-PPCREを使って適当に書いた置換の速度に負けた。
*流石にこれは恥ずかしいので*
CL-PPCREのソースを少し眺めてみることにしました。
気になったのは新たな文字列をどうやって生成しているか。
探してみると、
1. with-output-to-stringでストリームを作成 (先に配列を作ったりはしない)
2. write-stringでストリームに書き込み
という感じになっていました。
*勝利の鍵はwrite-string*
write-stringがどんな関数だったか覚えていなかったので、HyperSpecで調べてみると、
ストリームに文字列を書き出すというのはprincと同じですが、文字列専用な上に、
キーワード引数:startと:endをとり、部分文字列を書き出せるようになってました。
これはどう考えてもprincにsubseqで切り出した文字列を書き出させるより速いはず。
ということで、自作プログラムを書き直して再度速度を比較。

;; 自作プログラム
Evaluation took:
0.005 seconds of real time
0.004562 seconds of total run time (0.004562 user, 0.000000 system)
100.00% CPU
6,969,080 processor cycles
560,584 bytes consed
;; CL-PPCRE
Evaluation took:
0.025 seconds of real time
0.025393 seconds of total run time (0.025393 user, 0.000000 system)
100.00% CPU
38,050,333 processor cycles
2,368,328 bytes consed

やりました。今度は見事に勝利しました。
もっとも、簡単な置換しかできないプログラムが、
正規表現エンジンに負けてたら洒落にならないんですけど(笑)
(と言いながら、CL-PPCREを上手く使ったプログラムに負けたらどうしよう…)
*おまけ*
inner-line-convertはこんな関数です。
マクロdef-inner-convertがどうなっているかは、
各自ご想像にお任せします。

(defun inner-line-convert (line)
(declare (optimize (speed 3) (safety 0) (space 0)))
(declare (string line))
(def-inner-convert (line)
("<" "&lt;")
(">" "&gt;")
("''" "<b>" "''" "</b>")
("'''" "<i>" "'''" "</i>")
("[[" "]]" #'inner-link)))

Leave a Reply