MessagePack-JS (3)

cuzic です。

前回の投稿は ベンチマークテストにバグがあって、うまく処理できていなかったようです。ベンチマークテストのバグを修正すると、私の実装は eval に比べて 10倍以上遅いということが分かりました。

今日は一日かけて MessagePack のバイナリ文字列を Internet Explorer 環境で高速に処理する方法について、模索していました。

Internet Explorer 環境の特徴としては、以下の点があります。

  • 単純に JavaScript エンジンが遅い
  • responseText ではバイナリ文字列が処理できない。( FireFox 等のような overrideMimeType によるハックが使えない)
  • responseBody でバイト配列を返す
  • バイト配列は、 JavaScript では直接扱えない。
  • バイト配列の処理には JavaScript 以外の技術の利用が必須(VBScript の利用、XMLDOM の COM オブジェクトの利用など)

バイト配列の処理手法として当初は VBScript の利用による解決を模索したのですが、次の問題点を克服できませんでした。

  • メモリ使用量が非常に大きくなり、スタックオーバーフローが発生する場合さえある
  • 耐え難く遅い。(上記と同根の問題?)

そこで、現時点で github にコミットしているコードでは次の方式を採用しました。

  1. Microsoft.XMLDOM の COM オブジェクトを利用して、一旦 base64 エンコードする
  2. base64 エンコードした文字列を JavaScript で書いたデコード処理で 0〜255 までの数の配列に変換
  3. 2で得た配列を元に MessagePack の形式として解釈

いろいろ実験した中ではこの方式が IE8 環境でもっとも高速に動作するように思われました。

base64 へのエンコード処理は、Microsoft.XMLDOM を利用することで、

  function binary_to_string(binary){
      var xmldom = new ActiveXObject("Microsoft.XMLDOM");
      var bin = xmldom.createElement("bin");
      bin.dataType = "bin.base64";
      bin.nodeTypedValue = binary;
      return bin.text; // base64 文字列
  }

と簡単にできます。

base64 デコードについては、http://www.webtoolkit.info/javascript-base64.html を参考にしつつ、独自に実装しました。

あと、Microsoft.XMLDOM ではなく ADODB.Stream を使って、バイナリ文字列を扱う手法についても見当したのですが、私の InternetExplorer のセキュリティ設定では利用できない COM オブェジェクトであったため、採用しませんでした。