MPACKは、MessagePackシリアル化形式のエンコーダーとデコーダーのC実装です。そうです:
MPACKのコアには、バッファリングされたリーダーとライターと、動的に型付けされたノードのツリーにデコードするツリースタイルのパーサーが含まれています。ヘルパー関数を有効にして、予想されるタイプの値を読み取り、ファイルを操作し、バッファーを成長させたり、文字列を自動的に割り当てたり、UTF-8エンコーディングをチェックしたりすることができます。
MPACKコードは、コードベースに直接埋め込まれるほど小さいです。 Amalgamationパッケージをダウンロードして、 mpack.hとmpack.cをプロジェクトに追加します。
MPACKは、すべての最新のコンパイラ、すべてのデスクトップおよびスマートフォンOS、WebAssembly、Linuxカーネル内、さらにはArduinoなどの8ビットマイクロコントローラーをサポートしています。 MPACK機能セットは、コンパイル時にカスタマイズして、どの機能、コンポーネント、デバッグチェックがコンパイルされ、どの依存関係が利用可能かを設定できます。
ノードAPIは、メッセージパックデータの塊を動的に型のノードの不変のツリーに解析します。一連のヘルパー関数を使用して、各ノードから特定のタイプのデータを抽出できます。
// parse a file into a node tree
mpack_tree_t tree ;
mpack_tree_init_filename ( & tree , "homepage-example.mp" , 0 );
mpack_tree_parse ( & tree );
mpack_node_t root = mpack_tree_root ( & tree );
// extract the example data on the msgpack homepage
bool compact = mpack_node_bool ( mpack_node_map_cstr ( root , "compact" ));
int schema = mpack_node_i32 ( mpack_node_map_cstr ( root , "schema" ));
// clean up and check for errors
if ( mpack_tree_destroy ( & tree ) != mpack_ok ) {
fprintf ( stderr , "An error occurred decoding the data!n" );
return ;
}上記のコードでは追加のエラー処理は必要ないことに注意してください。ファイルが欠落または破損している場合、マップキーが欠落している場合、またはノードが予想されるタイプにない場合、特別な「nil」ノードとfalse/ゼロ値が返され、ツリーがエラー状態に配置されます。エラーチェックは、データを使用する前にのみ必要です。
上記の例は、ノードを自動的に割り当てます。メモリが制約された環境では、代わりにパーサーに固定ノードプールを提供できます。最大のパフォーマンスと最小限のメモリ使用量のために、予想APIを使用して、事前定義されたスキーマのデータを解析できます。
書き込みAPIは、構造化されたデータをメッセージパックにエンコードします。
// encode to memory buffer
char * data ;
size_t size ;
mpack_writer_t writer ;
mpack_writer_init_growable ( & writer , & data , & size );
// write the example on the msgpack homepage
mpack_build_map ( & writer );
mpack_write_cstr ( & writer , "compact" );
mpack_write_bool ( & writer , true);
mpack_write_cstr ( & writer , "schema" );
mpack_write_uint ( & writer , 0 );
mpack_complete_map ( & writer );
// finish writing
if ( mpack_writer_destroy ( & writer ) != mpack_ok ) {
fprintf ( stderr , "An error occurred encoding the data!n" );
return ;
}
// use the data
do_something_with_data ( data , size );
free ( data );上記の例では、成長可能なメモリバッファーにエンコードします。作家は、代わりに、メモリの割り当ての必要性を回避して、事前に割り当てられたまたはスタックに割り当てられたバッファー(化合物タイプの上昇サイズの)に書き込むことができます。ライターには、バッファがいっぱいになったときまたは書き込みが完了したときに呼び出すために、フラッシュ関数(ファイルやソケット書き込み機能など)を提供することもできます。
エラーが発生した場合、ライターはエラー状態に配置されます。作家は、あまりにも多くのデータが記述されている場合、間違った数の要素の数が記載されている場合、割り当て障害が発生した場合、データをフラッシュできない場合など、エラーにフラグを立てます。上記のコードでは追加のエラー処理は必要ありません。後続の書き込みは、ライターがエラー状態にあるときに無視されるため、すべての書き込みをエラーを確認する必要はありません。
上記の例ではmpack_build_map()を使用して、含まれるキー価値ペアの数を自動的に決定します。必要な要素の数を前すぐに知っている場合は、代わりにmpack_start_map()に渡すことができます。その場合、対応するmpack_finish_map()は、デバッグモードで、予想される要素の数が実際に記述されたと主張します。これは、他のメッセージパックC/C ++ライブラリができないものです。
MPACKには、非常に高いパフォーマンスと小さなコードフットプリントを維持しながら、機能が豊富です。これは、他のCパーサーと比較する短い機能テーブルです。
| mpack (v1.1) | msgpack-c (v3.3.0) | CMP (V19) | cwpack (v1.3.1) | |
|---|---|---|---|---|
| LIBCの要件はありません | ✓✓ | ✓✓ | ✓✓ | |
| 成長可能なメモリライター | ✓✓ | ✓✓ | ✓* | |
| ファイルI/Oヘルパー | ✓✓ | ✓✓ | ✓* | |
| ステートフルなエラー処理 | ✓✓ | ✓✓ | ||
| 増分パーサー | ✓✓ | ✓✓ | ✓✓ | |
| ツリーストリームパーサー | ✓✓ | ✓✓ | ||
| 複合サイズの追跡 | ✓✓ | |||
| 自動化合物サイズ | ✓✓ |
ここでは、テーブル内のさまざまなエントリの説明を含む、より大きな機能の比較テーブルをご覧ください。
このベンチマークスイートは、MPACKのパフォーマンスを、Schemaless Serializationフォーマットの他の実装と比較します。 MPACKは、すべてのJSONおよびメッセージパックライブラリ(CWPACKを除く)を上回り、一部のテストでは、MPACKは同等のデータについてRapidJSONよりも数倍高速です。
概念的には、メッセージパックはJSONと同様にデータを保存します。どちらも、数字や文字列などの単純な値で構成され、地図や配列に階層的に保存されます。では、代わりにJSONを使用しないのはなぜですか?主な理由は、JSONが人間が読みやすくなるように設計されているため、バイナリシリアル化形式ほど効率的ではないことです。
文字列、マップ、アレイなどの複合タイプは区切られているため、適切なストレージを事前に割り当てることはできません。オブジェクト全体を解析して、そのサイズを決定する必要があります。
文字列は、ネイティブエンコーディングに保存されません。引用符やバックスラッシュなどの特殊文字は、書かれたときに逃げて読むときに変換する必要があります。
数値は特に非効率的であり(特にバックフロートを解析する場合)、JSONは多くの数値を含む構造化データのベース形式として不適切になります。
バイナリデータはJSONによってまったくサポートされていません。アイコンやサムネイルなどの小さなバイナリブロブは、base64エンコードまたは渡されて渡される必要があります。
上記の問題は、デコーダーの複雑さを大幅に増加させます。フル機能のJSONデコーダーは非常に大きく、最小限のデコーダは、文字列の無効化やフロート解析などの機能を省略する傾向があり、代わりにこれらをユーザーまたはプラットフォームに任せます。これにより、プラットフォームに固有の困難でロケール固有のバグが発生し、セキュリティ脆弱性の可能性が高くなります。これにより、パフォーマンスが大幅に低下し、JSONがモバイルゲームなどのアプリケーションで使用するために魅力的ではありません。
JSONの空間の非効率性は、縮小と圧縮を通じて部分的に軽減できますが、パフォーマンスの非効率性はできません。さらに重要なことは、データを模倣して圧縮している場合、そもそも人間が読みやすい形式を使用するのはなぜですか?
MPACKビルドプロセスでは、MPACKをライブラリに組み込むことはありません。ユニットテストの構築と実行に使用されます。 MPACKを使用するためにMPACKまたはユニットテストスイートを構築する必要はありません。
MPACKのテスト方法については、test/readme.mdを参照してください。