PHPでJSONをカスタムバイナリ形式に置き換えました

Webやモバイルアプリ向けのリッチテキストを保存する必要があります。

長年、データベースには純粋なHTMLを使用していました。その後、編集と印刷を分離するためにJSONに切り替えました。

データ量が増えるにつれ、JSONが問題となりました。リンクを1つ変更するだけで、配列全体をパース、再構築、そして文字列化(stringify)しなければなりませんでした。このプロセスは低速で非効率でした。

そこで、PHPを使ってカスタムバイナリ形式を構築することにしました。

切り替えた理由は以下の通りです:

  • 速度:パースと検索が大幅に高速化されました。
  • コントロール:すべてをメモリにロードすることなく、特定のバイトを操作できます。
  • 構造:ネストされたツリーから、要素のフラットなリストへと移行しました。

ほとんどのリッチテキストのタスクにおいて、複雑なツリーは必要ありません。多くの場合、テキストや特定のタグを見つけるだけで十分です。オフセットの単純なツリーを持つ、要素のフラットな構造の方がうまく機能します。

PHPは低レイヤーの言語ではありません。ZigやCのようにバイト操作に最適化されているわけでもありません。しかし、PHPには適切なツールがあります:

  • pack() は数値や文字列を生のバイトに変換します。
  • unpack() はそれらのバイトを使用可能なデータに戻します。

マルチバイト文字列関数を使うのをやめました。代わりに、特定のバイトチャンクを読み取るようにしました。例えば、符号なし64ビット整数には正確に8バイトが必要です。

10,000回のループ後の結果:

旧JSONエンコード: 2.18s 旧JSONデコード: 0.86s 新バイナリエンコード: 1.19s 新バイナリデコード: 0.67s

バイナリ形式の方が高速です。一方でサイズも大きくなります。JSONの2倍、HTMLの3倍のサイズになります。私たちはサーバーサイドレンダリングを使用しているため、これは問題になりません。

カスタム形式を構築する場合は、あるルールに従ってください。それは「仕様書を書くこと」です。形式を明確に文書化してください。そうしないと、後で後悔することになります。

作業には1週間かかりましたが、それだけの価値はありました。

出典: https://dev.to/tomj/i-replaced-json-with-a-custom-binary-format-in-php-mok