自作 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が固まるので要注意です。
    • なので、その辺も自力で何とかしています。