Let's start Scheme

2012-05-19

Unicode変換処理の実行時間差

Larcenyのベンチマークにbv2stringという処理がある。名前の通りバイトベクターからストリングに変換する処理である。普通の処理と違うのは、これがあほかというくらい繰り返す点であろう。最近Transcoder周りを改善したのでちょっとチャレンジしてみた。

っで、標題の件である。この処理については意外なことに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 total
Ypsilonは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