っで、標題の件である。この処理については意外なことにYpsilonが苦手としている。逆にSagittariusはかなり高速に処理をする。(moshはもっと速いんだけど、出てくる結果が不正確)。以下はbv2stringの中から抜粋して上記3つの処理系で速度を計ってみた結果。
(import (rnrs) (rnrs mutable-strings)) (define (test-char-range name lo hi tostring tobytevector) (let* ((n (+ 1 (- hi lo))) (s (make-string n)) (replacement-character (integer->char #xfffd))) (do ((i lo (+ i 1))) ((> i hi)) (let ((c (if (or (<= 0 i #xd7ff) (<= #xe000 i #x10ffff)) (integer->char i) replacement-character))) (string-set! s (- i lo) c))) (string=? (tostring (tobytevector s)) s))) (define (test-exhaustively name tostring tobytevector) (test-char-range name #x10000 #x1ffff tostring tobytevector)) (test-exhaustively "UTF-8" utf8->string string->utf8) (test-exhaustively "UTF-16" (lambda (bv) (utf16->string bv 'big)) string->utf16) (test-exhaustively "UTF-32" (lambda (bv) (utf32->string bv 'big)) string->utf32)
$ time sash test.scm sash test.scm 0.73s user 0.12s system 94% cpu 0.906 total $ time mosh test.scm GC Warning: Repeated allocation of very large block (appr. size 524288): May lead to memory leak and poor performance. mosh test.scm 0.52s user 0.12s system 97% cpu 0.656 total $ time Ypsilon test.scm Ypsilon test.scm 0.01s user 0.06s system 0% cpu 1:49.86 totalYpsilonはWindows版をCygwin上で走らせているのでトータルのタイムのみが出ている点に注意。
moshが最速なのだが、結果が不正確である。実際string=?の部分を出力するとUTF-8のテストで#fが返っている。 (これはbv2stringの一部なのでUTF-8だけなのだが、全部を走らせると鬼のように不正確な値を返す。恐らくUTF-16及びUTF-32に変換した後のチェックが省かれているのだろう)。
Sagittariusは実用的な速度で正確な結果を返す。ただし、開発版である。0.3.2以前は不正確な値を返す。これはmoshの項で記載したチェックが省かれていたため。
以外だったのはYpsilonである。今まで異次元の速さを誇っていたのがここにきて異次元の遅さになってしまっている。 Ypsilonのutf16->string、string->utf16、utf32->string及びstring->utf32はSchemeで実装されているのでそれが原因かと思ったのだが、utf8->stringとstring->utf8も遅かった。(ちなみに、この2つはC++で実装されている。見間違えていなければ)。ここからは推測になるのだが、これは内部エンコーディングの差ではないだろうか?moshとSagittariusは内部で文字列をUCS4で持っているが、Ypsilonはutf-8で持っている。なので、bv -> ucs4 -> utf8と2回変換が走ることになって、その分のオーバーヘッドが処理時間に如実に反映されているのではないだろうか?
なにはともあれ、一つでもYpsilonに勝ったと言える部分があるのは嬉しいことである。
No comments:
Post a Comment