JSON よりもフットプリントが大幅に小さい単純な Javascript オブジェクトツリーの適切なシリアライゼーション/デシリアライゼーション形式はありますか? BSONはあまり印象的ではありません。
JSON の余分なオーバーヘッドは、多くのオブジェクトが同じプロパティ セットを共有するツリーでは特に重要です。理論的には、プロパティ名が繰り返されないように、オブジェクト配列内のスキーマを検出できるはずです。
JSON よりもフットプリントが大幅に小さい単純な Javascript オブジェクトツリーの適切なシリアライゼーション/デシリアライゼーション形式はありますか? BSONはあまり印象的ではありません。
JSON の余分なオーバーヘッドは、多くのオブジェクトが同じプロパティ セットを共有するツリーでは特に重要です。理論的には、プロパティ名が繰り返されないように、オブジェクト配列内のスキーマを検出できるはずです。
Gzip は高速です。とても早い。そして、私はこれが (実用性と効率性の両方の点で) リーン オブジェクトの輸送に最適なソリューションであることにかなりの自信を持っています。
ポイントを説明するために、ステージング サイトの 1 つで簡単なサンプルを作成しました。
http://staging.svidgen.com/ajax/test-a.jsは、5,000 行の単純なデータを生成し、汚染されていない生の JSON を出力します。
$data = array();
for ($i = 0; $i < 5000; $i++) {
$data[] = array(
'value-a' => $i,
'value-b' => pow($i,2),
'value-c' => pow($i,3)
);
}
print json_encode($data);
gzip された応答は65KBで、要求、ビルド、シリアル化、および送信に約 357 ミリ秒かかります。式からクライアント サイズの解析を省略すると、スループットは182KB/sになります。送信された274KBの生データを考慮すると、これは767KB/s の実効スループットです。応答は次のようになります。
[{"value-a":0,"value-b":0,"value-c":0},{"value-a":1,"value-b":1,"value-c":1} /* etc. */]
別の形式であるhttp://staging.svidgen.com/ajax/test-b.jsは、同じ 5k 行の単純なデータを生成しますが、データをより効率的なインデックス付きの JSON シリアル化に再構築します。
$data = array();
for ($i = 0; $i < 5000; $i++) {
$data[] = array(
'value-a' => $i,
'value-b' => pow($i,2),
'value-c' => pow($i,3)
);
}
$out_index = array();
$out = array();
foreach ($data as $row) {
$new_row = array();
foreach ($row as $k => $v) {
if (!isset($out_index[$k])) {
$out_index[$k] = sizeof($out_index);
}
$new_row[$out_index[$k]] = $v;
}
$out[] = $new_row;
}
print json_encode(array(
'index' => $out_index,
'rows' => $out
));
gzip された応答は59.4KBで、要求、ビルド、シリアル化、および送信に約 515 ミリ秒かかります。式からクライアント サイズの解析を省略すると、スループットは115KB/sになります。送信された128KBの生データを考慮すると、これは248KB/s の実効スループットです。応答は次のようになります。
{"index":{"value-a":0,"value-b":1,"value-c":2},"rows":[[0,0,0],[1,1,1] /* etc. */ ]}
したがって、非常に単純な例では、生の再構成されたデータは、元の生データよりも 50% 以上小さくなっています。ただし、gzip で圧縮すると 9% しか小さくなりません。この場合のコストは、合計リクエスト時間の 44% の増加です。
データを再構築するためにバイナリ ライブラリを作成した場合、その 44% を大幅に削減できると思います。しかし、それでも価値がある可能性は非常に低いです。構造を「通常」にエンコードして利益を得るよりも 9% 以上長くかかることなく、データをシリアル化する必要があります。
再構築または「代替シリアライゼーション」のヒットを回避する唯一の方法は、サーバー側のすべてのオブジェクトを、最初から最後まで厄介なインデックス付きの方法で操作することです。そして、ハードウェアのパフォーマンスを無視できるレベルまで引き出す必要がない限り、それは本当にひどい考えです。
どちらの場合も、gzip によるスペースの節約は、代替の JavaScript 互換フォーマットを使用して達成できる範囲をはるかに超えています。
(そして、クライアント サイズの解析も考慮していません。これは、「通常の」JSON や XML ではないものにとって非常に重要です。)
組み込みのシリアル化ライブラリと gzip を使用するだけです。
JSON をより「データベース」形式に変換してから、通常のオブジェクトに戻すことができます。結果は、時にはそれだけの価値があります。
// Typed on the fly
var dict = [
["FirstName", "LastName"],
["Ken", "Starr"],
["Kermit", "Frog"]
];
次に、次のような方法で辞書をループできます。
// Again, typed on the fly
var headers = dict[0];
var result = []
var o;
for (var i = 0 + 1; i < dict.length; i++) {
o = {}
for (j = 0; j < headers.length; j++) {
o[headers[j]] = dict[i][j];
}
result.push(o);
}
非常に高速な圧縮ライブラリがあります。したがって、コンパクトなフォーマットがコンパクトでないフォーマットに圧縮を加えたものよりも優れているとは限りません。
手元にリンクはありませんが、元 protobuf デザイナーがこのアプローチを推奨したと思います。
MessagePackをチェックしてください。これは、JSON や BSON と非常によく似たセマンティクスを持つかなりコンパクトなバイナリ形式です。
短い配列 (最大 16 要素)、マップ (最大 16 ペア)、および文字列 (最大 32 バイト) には、1 バイトのオーバーヘッドがあります。小さな整数 (-32 から 128) は合計で 1 バイトしか使用しません。