JSON パーサの性能評価

[追記] Sagittarius では 053a8ad0a38c で高速な JSON ライブラリが導入されました。[/追記]

Scheme 処理系 Sagittarius が持っている JSON パーサライブラリを以前にいじったことがある。 Sagittarius の JSON パーサライブラリは下請けに packrat ライブラリが使われているのだが、この場合の packrat は性能に寄与していないのではないかと疑っている。 packrat は途中経過をメモ化することに特徴があるわけだが、 JSON は LL(1) 文法であり、やたらに記憶する意味はないだろうという予想だ。 そこで、性能を評価してみることにした。

評価するにしても比較対象が必要なのでウェブ検索してみると、 Guile 用にまとめられたライブラリが見付かった。 愚直に再帰下降型として実装したもののようだ。

そしてそれを R6RS 用に修正するパッチを用意した。

ではいよいよ比較してみよう。

#!r6rs
(import (rnrs)
        (json)
        (json parser)
        (time))

(let ((json-string (call-with-input-file "test.json" get-string-all)))
  (time (json-read (open-string-input-port json-string)))
  (time (json->scm (open-string-input-port json-string))))

テストに用いたデータは仲間内でやりとりしたチャットのログ五千件分 (約 1 メガバイト) である。 その性質上、データを公開するわけにはいかないので、ベンチマークをとりたい場合は適当なデータを各自で用意してもらいたい。

結果は…

;;  (json-read (open-string-input-port json-string))
;;  33.420065 real    33.072212 user    0.343202 sys
;;  (json->scm (open-string-input-port json-string))
;;  1.107601 real    0.967206 user    0.140401 sys

およそ 30 倍の差となった。

残念ながら比較に用いた JSON パーサライブラリは GPL なので MIT ライセンスの Sagittarius に混ぜることは出来ないが、これほどの差があるのならフルスクラッチで JSON パーサを書いても充分に意義があると思う。 JSON はかなり簡単な書式ということもある。

ちなみに Sagittarius の JSON パーサライブラリは Chicken 用のものから移植されたものだ。 最初に書いた人は何を思って packrat を使ったのか…。

Document ID: 8ddac607af852837af9b66b1c3d8210c

時刻:
ラベル:

0 件のコメント:

コメントを投稿