[JSON] コイツ、速いぞ! きっとFirefoxのXMLパーサが遅いんだ。

ajax のデモも兼ねて、うちのサイトのトップページの右側のサイドバーにいろいろと
情報を載せていたら、5項目でXMLファイルの合計容量が190KB近くになっていた。
プレーンなデータしか記述できない XML は安全で、再利用性も高そうな気がするし、
Animation.CubeのようにクライアントPCの潤沢なCPU資源を浪費する
富豪プログラミングが許容される時代だと思って、好き勝手やっていたけど、
さすがにトップページの表示が遅いのは快適じゃない。
 
いくら ajax で async モードを使っていても、Firefox の XML パーサは遅くて、
しかも XML のパース処理中は他の処理がロックしてしまう。ロックは避けたい。
 
JSON::Syck モジュールで、サーバ側で予め JSON ファイルに変換したものを
利用するように変更してみた。
RSS ファイルと同じデータ構造なら、既存プログラムの変更も少なくて済む。
トップページの表示は10件までなので、JSON 版ではアイテム数も制限して、
URL・ページタイトル・更新日時以外の不要な情報も削除しちゃう。
 
すると、XML=190KB → JSON=14KB に減った!

・サイト全体の更新情報
      46221 http://www.kawa.net/index.rdf
      2100 http://www.kawa.net/rss/index.json

・はてなブックマークから注目エントリー10件
      47176 http://www.kawa.net/rss/hatena-bookmark.rss
      1786 http://www.kawa.net/rss/hatena-bookmark.json

・del.icio.us で最近見てきたページ10件
      16005 http://www.kawa.net/rss/recent-delicious.rss
      1913 http://www.kawa.net/rss/recent-delicious.json

・flickr にアップロードした写真10枚(うち最新9枚だけ表示)
      21152 http://www.kawa.net/rss/recent-flickr.rss
      3243 http://www.kawa.net/rss/recent-flickr.json

・ajaxcom の新着コメント
      18252 http://www.kawa.net/service/com/ajaxcom-data/recent.xml
      2939 http://www.kawa.net/service/com/ajaxcom-data/recent.json

・ajaxtb の新着トラックバック
      39112 http://www.kawa.net/service/tb/ajaxtb-data/recent.xml
      2341 http://www.kawa.net/service/tb/ajaxtb-data/recent.json

XML ファイルは冗長だとよく言うけれど、10倍とは。
実際には、アイテム件数制限や要素削除の効果が大きいから
アイテム件数制限や要素削除したバージョンの XML ファイルも作成して
比較してあげた方が公平だけど、ともかく、各 JavaScript 側も JSON 版に
切替えたら XML パーサのロックもなくなり、表示も速く快適になった。

こうも違うと、改めて XML で比較する気がしないです~♪
XML に固執していた僕が青かった。素直に JSON を使おう。

※IE7β2、Firefox、Opera、Safari、OmniWeb で動作確認済。

rss2json.pl


クライアント側 JavaScript では、XML.ParseXML を利用しています。
サーバ側 Perl では、XML::FeedPP を使って JSON に変換しました。
参考に、RSS→JSON 変換のスクリプトを置いておきます。

#!/usr/bin/perl
# rss2json.pl
# Copyright 2006 Yusuke Kawasaki http://www.kawa.net/

# JSON または JSON::Syck のどちらかが必須。
# use JSON;
    use JSON::Syck;
    use XML::FeedPP;

# JSON出力するアイテム数と拡張要素

    my $MAX_ITEM = 10;
    my $ITEM_KEYS = [qw( media:thumbnail@url media:thumbnail@width media:thumbnail@height )];

# RSSファイル名(またはURL)と、出力するJSONファイル名

    my $file = shift @ARGV;
    my $out = shift @ARGV;
    unless ( defined $out ) {
        $out = $file;
        $out =~ s/\.[^\.]+$/.json/g;
    }

# XML::FeedPP モジュールでRSS/RDF/Atomファイルを展開する(形式問わず)

    my $feed = XML::FeedPP->new($file);
    $feed->normalize();
    $feed->limit_item( $MAX_ITEM );

# チャンネル情報を取り出す

    my $channel = {};
    $channel->{title} = $feed->title();
    $channel->{link} = $feed->link();
    $channel->{pubDate} = $feed->pubDate();

# アイテム情報を取り出す

    my $list = [];
    foreach my $item ( $feed->get_item() ) {
        my $hash = {
            title => $item->title(),
            link => $item->link(),
            pubDate => $item->pubDate(),
            author => $item->author(),
        };
        foreach my $key ( @$ITEM_KEYS ) {
            my $val = $item->get($key) or next;
            $hash->{$key} = $val;
        }
        push( @$list, $hash );
    }
    $channel->{item} = $list;

# JSON 形式に変換する

    my $tree = { rss => { channel => $channel }};
    my $text = JSON::Syck::Dump( $tree );
# my $text = objToJson( $tree );
    $text .= "\n";

# 前回の出力ファイルがあれば、内容を読み込む

    open( IN, $out ) and do {
        local $/ = undef;
        my $prev = <IN>;
        close( IN );
        if ( $prev eq $text ) {
            print STDERR "Nothing changed.\n";
            exit 0;
        }
    };

# 新しい内容で書き出す

    open( OUT, "> $out" ) or die "$! - $out\n";
    print OUT $text;
    close( OUT );

# 終了~♪

    print STDERR "$out updated.\n";


使い方は、以下の通り。

perl ./rss2json.pl index.rss
perl ./rss2json.pl http://www.kawa.net/index.rdf hoge.json
第1形式は、ローカルの index.rss を読み取って index.json を作成します。
第2形式は、サーバ上の index.rdf を読み取って hoge.json を作成します。
フィードは RSS・RDF・Atom どれでもOKです。

////

え? やっぱり Plagger でも同じこと(RSS→JSON変換)できるの?

ブログ気持玉

クリックして気持ちを伝えよう!

ログインしてクリックすれば、自分のブログへのリンクが付きます。

→ログインへ

なるほど(納得、参考になった、ヘー)
驚いた
面白い
ナイス
ガッツ(がんばれ!)
かわいい

気持玉数 : 2

なるほど(納得、参考になった、ヘー) なるほど(納得、参考になった、ヘー)

この記事へのコメント

JSONでRSSリーダつくってみました(ono)
2007年01月21日 12:17

http://test1.mydns.jp/chktest.htm

jklParseXMLのページにも書込んでたのですが、「JSON」の記述はこちらだった事を思い出したので、こちらにも書込ませて頂こうと思いました(すいません)

動作はこういう感じです
yahoo news
http://test1.mydns.jp/chktest.htm?url=http://headlines.yahoo.co.jp/rss/fsi.xml
auction
http://test1.mydns.jp/chktest.htm?url=http://api.auctions.yahoo.co.jp/AuctionWebService/V1/CategoryLeaf?appid=YahooDemo&category=42223

なかみはこうです
http://test1.mydns.jp/chktest_.htm


http://groups.yahoo.co.jp/group/YJDN/message/63
先日1/21にひきつづきJSON(とTreePP
2007年02月04日 22:57
.pmで、今度は「webとオークション両方検索」


するというものをちょっと作ってみました。


http://test1.mydns.jp/test3/dvdrecorder.htm

   「DV-DH500Wでテスト」

というボタンを押すと、web上のデータの表示のされかたがわかるかと思います。

あとこちらは「株価コード」でyahooマップ(と企業情報)を表示させるというものです。
http://www.test1.mydns.jp/yapi/zz.html?9955

(ここにも載せましたが。http://groups.yahoo.co.jp/group/YJDN/messages/79?expand=1 )
urlがとちゅうまでしか書かれていませんでした
2007年02月16日 13:09
ヤフー株式掲示板9474ゼンリンのNo5041あたりの書込みのurlでした。先程載せてたのは。

(A) http://test1.mydns.jp/gmap?test (/index.html?test、と実際は続いている。)
(B) http://test1.mydns.jp/gmap/test.htm?test
この2つは、それぞれの、21行めあたりの最後のほうに、上はというタグをつかっており下のはそのタグを
  つかってないだけで、それ以外は、”全くおんなじ内容のhtmlファイル”、のはずなのですが

上のhtmlファイルのほうだけかならず「操作中止」となって終了してしまうようなのです。

この記事へのトラックバック