Hatena::ブログ(Diary)

latest log このページをアンテナに追加 RSSフィード

2010-06-06

自作 MessagePack のベンチ取ってみた

http://pigs.sourceforge.jp/blog/20100606/msgpack.htm

IE6 28秒ぐらい
IE8 10秒ぐらい
Chrome6 8.5秒ぐらい
Firefox3.6.3 9秒ぐらい
Opera10.50 不明

約1MBのデータだと、体感的に IE8 と Firefox3.6, Google Chrome 6 で大差ない感じになってる気がします。

# 回線や距離もあるでしょうが

サーバからバイナリデータを受信する処理は、IE6でもうまいことやれてますが、Operaだと、application/octet-stream で先頭数バイトがちゃんと受信できず全滅してます。

ファイル一覧はこちら

http://pigs.sourceforge.jp/blog/20100606/

http://pigs.sourceforge.jp/blog/20100606/msgpack.zip からファイル一式がダウンロードできます。

*.php の中身はこんな感じです

<?php
$fileName = "1byte.bin";
header('Content-Type: application/octet-stream');
header('Content-Length: ' . filesize($fileName));
readfile($fileName);
?>

バイナリデータの受信部分のロジックはこんな感じです

uu.ajax.binary(url) を呼ぶと、非同期にバイナリデータを受信し、ByteArray( [0x00, 0xff, ...] ) を返します。

// === uu.ajax.binary ===
//#include uupaa.js
//#include ajax/ajax.js

uu.ajax.binary || (function(uu) {

uu.ajax.binary = uuajaxbinary; // uu.ajax.binary(url:String, callback:Function, option:Hash = {})

// uu.ajax.binary
function uuajaxbinary(url,      // @param String:
                      callback, // @param Function: callback function
                      option) { // @param Hash(= {}):
    function readyStateChange() {
        if (xhr.readyState === 4) {
            var ok = xhr.status >= 200 && xhr.status < 300;

            callback({ ok: ok, xhr: xhr, data: ok ? toBinary(xhr) : [] });
        }
    }

    var xhr = uu.ajax.create();

    xhr.onreadystatechange = readyStateChange;

    if (!uu.ie) {
        if (xhr.overrideMimeType) {
            xhr.overrideMimeType("text/plain; charset=x-user-defined");
        } else {
            xhr.setRequestHeader("Accept-Charset", "x-user-defined");
        }
    }
    xhr.open("GET", url, true); // ASync
    xhr.send(null);
}

// inner - to binary
function toBinary(xhr) { // @param XMLHttpRequest:
                         // @return ByteArray:
    var rv = [], data,
//{{{!mb
        loop, remain, v0, v1, v2, v3, v4, v5, v6, v7,
//}}}!mb
        i = 0, iz;

//{{{!mb
    if (!uu.ie) {
//}}}!mb
        data = xhr.responseText;
        iz = data.length;
        for (; i < iz; ++i) {
            rv[i] = data.charCodeAt(i) & 0xff;
        }
//{{{!mb
    } else {
        data = vbstr(xhr.responseBody);
        iz = vblen(xhr.responseBody);

        loop = Math.ceil(iz / 2);
        remain = loop % 8;
        i = -1;

        while (remain--) {
            v = data.charCodeAt(++i); // 0x00,0x01 -> 0x0100
            rv.push(v & 255, v >> 8);
        }
        remain = loop >> 3;
        while (remain--) {
            v0 = data.charCodeAt(++i);
            v1 = data.charCodeAt(++i);
            v2 = data.charCodeAt(++i);
            v3 = data.charCodeAt(++i);
            v4 = data.charCodeAt(++i);
            v5 = data.charCodeAt(++i);
            v6 = data.charCodeAt(++i);
            v7 = data.charCodeAt(++i);
            rv.push(v0 & 255, v0 >> 8, v1 & 255, v1 >> 8,
                    v2 & 255, v2 >> 8, v3 & 255, v3 >> 8,
                    v4 & 255, v4 >> 8, v5 & 255, v5 >> 8,
                    v6 & 255, v6 >> 8, v7 & 255, v7 >> 8);
        }
    }
//}}}!mb
    return rv;
}

// --- init ---
//{{{!mb
uu.ie && document.write('<script type="text/vbscript">\
Function vblen(b)vblen=LenB(b)End Function\n\
Function vbstr(b)vbstr=CStr(b)+chr(0)End Function</'+'script>');
//}}}!mb

})(uu);

反省会

  • VBScript 周りは、最終的なコードだけ見ると大したことやってないように見えるけど、色々と試行錯誤がありました。
    • バイナリデータを JScript だけで受信できない IE は、かなりどうかしてる。
  • http://bit.ly/a0zwGd で紹介されているような VBScript 内でレスポンスデータを AscB() や MidB() でコネて配列化するコードは、200〜300kBのデータを食わせるだけでIEが固まるので要注意です。
    • なので、その辺も自力で何とかしています。

えむけいえむけい 2010/06/06 21:50 ・Operaではopenとsendの間にoverrideMimeTypeしないとうまくいかないみたいです。
・IE9pp2では、JScript側でxhr.responseBodyへの参照を作成することさえできません(そこでスクリプトエラーになります)。xhrをVBScriptに渡して、VBScript側でresponseBodyを参照する必要があります。

edvakfedvakf 2010/06/07 04:42 Opera に報告しときました。
http://orera.g.hatena.ne.jp/edvakf/20100606/1275853067

uupaauupaa 2010/06/07 16:47 えむけい さんコメントありがとうございます。

まさにそのとおりでした。
いただいたコメントを参考に、OperaとIE9に対応した版を作りました。
http://d.hatena.ne.jp/uupaa/20100607/1275896483


edvakf さんコメントありがとうございます。

バグレポート自分で書かないと…と思いつつ、いつもすみません。感謝しております。

えむけいえむけい 2010/08/05 23:33 IE9pp4では、
var a = { xhr: xhr };
vblen(a);
みたいにしないとVBScriptに渡せなくなったようです。
この調子で互換性が低下していくと、そのうちVBScriptサポートが廃止されるんじゃないかと心配になってきます。XHR2を実装する前に廃止されても困るんですが…。

uupaauupaa 2010/08/08 10:07 ぐはっ。IE9 ひどい
MSの製品の売りは互換性だったはずなのに

えむけいえむけい 2010/09/16 05:29 あんまりひどいのでconnectにフィードバックしてみたおかげかどうかわかりませんが、IE9 betaでは
1. ActiveXObject("Msxml2.XMLHTTP")でresponseBodyを渡す: OK
2. ActiveXObject("Msxml2.XMLHTTP")でxhrを直接渡す: NG
3. ActiveXObject("Msxml2.XMLHTTP")でxhrをラップして渡す: OK
4. ネイティブXMLHttpRequestでresponseBodyを渡す: OK
5. ネイティブXMLHttpRequestでxhrを直接渡す: OK
6. ネイティブXMLHttpRequestでxhrをラップして渡す: OK
のように改善されていました。
互換表示にすると2.もOKになったのでIE9モードで2.がNGなのは仕様なのかも。

えむけいえむけい 2010/10/30 16:19 Platform Preview 6でこの問題は修正されて、IE9対応のために特別なことをする必要はなくなりました。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト

コメントを書くには、なぞなぞ認証に回答する必要があります。

トラックバック - http://d.hatena.ne.jp/uupaa/20100606/1275808324