JSON パーサの性能評価
[追記] Sagittarius では 053a8ad0a38c で高速な JSON ライブラリが導入されました。[/追記]
Scheme 処理系 Sagittarius が持っている JSON パーサライブラリを以前にいじったことがある。 Sagittarius の JSON パーサライブラリは下請けに packrat ライブラリが使われているのだが、この場合の packrat は性能に寄与していないのではないかと疑っている。 packrat は途中経過をメモ化することに特徴があるわけだが、 JSON は LL(1) 文法であり、やたらに記憶する意味はないだろうという予想だ。 そこで、性能を評価してみることにした。
評価するにしても比較対象が必要なのでウェブ検索してみると、 Guile 用にまとめられたライブラリが見付かった。 愚直に再帰下降型として実装したもののようだ。
そしてそれを R6RS 用に修正するパッチが以下である。
https://gist.github.com/SaitoAtsushi/12126187f8b50413b4cd
ではいよいよ比較してみよう。
#!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