UNF: Common Lisp版
しばらく(私的には)プログラミングから離れた生活が続いていたので、肩慣らしを兼ねてUNF(Unicode正規化ライブラリ)のcommon lisp版(cl-unf)を作成。
いつものようにSBCLで作成し、SBCL向けに最適化されているが、UTF-32に対応しているなら、他の処理系でも一応動作はするはず。
使用例
(require :unf) ;; NFKC正規化 (unf:normalize "ABCガギグ" :nfkc) --> "ABCガギグ" ;; 上の簡略版 (unf:nfkc "ABCガギグ") --> "ABCガギグ"
計時
C++版のUNFとJavaのjava.text.Normalizerとの比較。
C++及びJavaの計時用のプログラムや使用しているデータ(テキスト)に関してはUNF : Unicode正規化ライブラリ - sileの日記を参照のこと。
cl-unf用には、以下のプログラムを使用。
;; sbcl-1.0.40 ;; テキスト読み込み関数 (defun read-lines (path) (with-open-file (in path) (loop FOR line = (read-line in nil nil) WHILE line COLLECT line))) ;; 計時用データ (defvar *souseki* (read-lines "souseki.txt")) (defvar *keizai* (read-lines "keizai.txt")) ;; 計時関数 (defun unf-time (lines form) (time (dolist (line lines 'done) (unf:normalize line form)))) ;; 実行例 (unf-time *keizai* :nfd) ; NFDで正規化 Evaluation took: 0.037 seconds of real time 0.036002 seconds of total run time (0.036002 user, 0.000000 system) [ Run times consist of 0.004 seconds GC time, and 0.033 seconds non-GC time. ] 97.30% CPU 72,473,421 processor cycles 11,477,392 bytes consed --> DONE
結果:
処理時間(秒): souseki.txt*1 | 処理時間(秒): keizai.txt*2 | |
Normalizer(Java) | NFD: 0.063s NFC: 0.040s NFKD: 0.067s NFKC: 0.069s | NFD: 0.037s NFC: 0.030s NFKD: 0.043s NFKC: 0.048s |
UNF(C++) | NFD: 0.133s NFC: 0.073s NFKD: 0.131s NFKC: 0.078s | NFD: 0.048s NFC: 0.027s NFKD: 0.056s NFKC: 0.043s |
cl-unf(Common Lisp) | NFD: 0.060s NFC: 0.033s NFKD: 0.061s NFKC: 0.061s | NFD: 0.027s NFC: 0.018s NFKD: 0.032s NFKC: 0.036s |
この結果を見ると、cl-unfが三者の中で一番速くなっている。
C++版はUTF-8文字列、JavaのNormalizerは(おそらく)UTF-16文字列、cl-unfはUTF-32文字列、をそれぞれ対象としており、Unicode正規化のような処理の場合は、余計な変換等が不要な分だけUTF-32文字列を直接扱う方が有利なので、それほど意外な結果でもないかもしれないが、Javaより速かったのは少し驚いた。
計時方法や入力テキストデータによって、また変わってくるとは思うけど。