ホーム >> 左脳Script >> Adobe Flash >> Action Script >> XML は String で結合する方が早い

XML は String で結合する方が早い


ニコニコ動画のコメントは、人気動画ならば刻々と変化していきます。
久しぶりにアノ動画を・・・と閲覧すると、コメントが様変わりしていて、また違った雰囲気で動画を楽しむ事が出来たりします。しかし逆に、荒らされて「昔のコメント状態の方が良かった」なんて事も良く在る話です。
ダウンローダーでローカルに保存してしまうと、コメントの変化を楽しむ事は出来なくなりますが、それはコメントデータを新たに取得しなおせば良い事。そこで、間を置いて再取得したコメントデータを合理的に保存する為に、コメントデータのマージをするルーチンを作りましたが・・・

注意)コードの実行は、AIR SDK 1.5.3 の adl.exe にて行っています。全ての環境で同じ結果が出るとは限りません。

ニコニコメント結合コード

コードはそれほど難しくもなく。


private function commentsMarge(a:XML, b:XML):XML 
{
    var aTime:Number = Number(a.thread.@server_time);
    var bTime:Number = Number(b.thread.@server_time);
    if (    aTime > bTime   )
    {   //  b の方が新しいデータ。になるよう入れ替える。
        var tmp:XML = a;
        a = b;
        b = tmp;
        tmp = null;
    }
    //
    var chat:XML;
    var no:Number;
    //  配列へ
    var orAry:Array = new Array();
    for each(chat in a.chat)
    {
        no = Number(chat.@no);
        orAry[no] = chat;
    }
    //  結合:noをユニークなIDとして結合。
    for each(chat in b.chat)
    {
        no = Number(chat.@no);
        orAry[no] = chat;   //  レス番が被れば、より新しいデータで上書き。
    }
    //  整列
    var numArray:Array = new Array();
    for each(chat in orAry) numArray.push(chat);
    orAry = null;
    numArray.sort(function (a:XML, b:XML):int 
    {
        var an:Number = Number(a.@no);
        var bn:Number = Number(b.@no);
        if (    an > bn )   return  1;
        if (    an < bn )   return  -1;
        return  0;
    });
    //  XMLへ
    var xml:XML =<packet/>;
    xml.appendChild(b.view_counter);    //  視聴カウント
    //
    for each(chat in numArray)  xml.appendChild(chat);
    //
    return  xml;
}

引数に与えられる、xml はニコニコから取得したコメントデータXML そのままです。
コメントのレス番順にソートしたものを返してくれます。


重い・・・とてもとても重い

1000コメントあるコメントデータに、新たに1000コメントあるコメントデータを結合してみました。コメント取得の間が結構開いていたので、内容が被るコメントが無く、結合後2000コメントのデータになりました。
が、この処理にえらい時間がかかるのです。ルーチンの実行から値が返ってくるまでを getTimer で測ったところ、1400msec ほどかかります。Action Script の処理能力から言って、2000個のデータをどうこうにするのに、1秒もかかるハズはありません。

どこに時間がかかっているのか追求していくと・・・ルーチン最後のループに問題があったようです。

for each(chat in numArray)  xml.appendChild(chat);
結合後の、XML再構成にえらい時間がかかっている事がわかりました。普通の Array に、2000個の XML が有り、これを XML に再結合するのに 1200msec 程かかっている事が判りました。
ただの XML の子ノード追加なのに何故こんなに重いのでしょうか。


文字列にしてみる

最終的に「結合できれば良い」ので、ダメ元で String にして繋げてから XML に戻す方法にしてみたところ・・・

var r:String = "";
for each(chat in numArray)  r += chat.toXMLString();
var xl:XMLList = new XMLList(r);
xml.appendChild(xl);
1200msec → 250msec と劇的に改善しました。おィい?大丈夫か XML!
しかし、XML の各ノードのオブジェクトとしての整合性や、機能などを考えると仕方ないのかもしれません。

この時点で、XML のデータ操作は、出来ることなら文字列でやった方が早いという事が言えると思います。

文字列の結合の部分をもうちょっと追求して・・・

xml.appendChild(
    new XMLList(
        numArray.map(
            function (chat:XML, index:int, arr:Array):String
            {
                return chat.toXMLString();
            }
        ).join("")
    )
);
250msec → 100msecと、カナリの短縮に。

最終的に、およそ10倍の速度アップに成功しました。


ちなみに、appendChild とほぼ同機能の以下の記述を試したところ・・・

for each(chat in numArray)  xml.* += chat;
なんと、8500msec !! 機能は同じでも、やっている事が違うのでしょうか。この重さは問題が在るように思いますが・・・


結論

XML のデータ結合は一旦文字列にしてからの方が早い。カナリ。
この件の検証結果が、どの程度応用が効くかは状況にも寄りますが、多量のデータを纏めるなんて場合には、使えると思います。



トラックバック(1)

トラックバックURL: http://n-yagi.0r2.net/sanoupulurun/mt-tb.cgi/249

XMLの内容をソートするメソッドというものは存在しません。Arrayのようにデータ構造が単純ではない為、データに合う実装方法を製作者側が明示的に記述する必... 続きを読む

コメントする

ホーム >> 左脳Script >> Adobe Flash >> Action Script >> XML は String で結合する方が早い

アーカイブ

このブログ記事について

このページは、n-yagiが2010年1月11日 10:13に書いたブログ記事です。

ひとつ前のブログ記事は「AIR から WebCamera を使うには」です。

次のブログ記事は「HTMLタグのレンダリングについての疑問」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

Creative Commons License
このブログはクリエイティブ・コモンズでライセンスされています。