Base64は64種類の文字を使って8bitのバイナリデータを6bitにエンコードしますが、Base122は可変長文字列エンコード方式UTF-8を使った7bitでエンコードする方式です。変換後の文字列はなかなかスゴイことになります。
GitHubにNode.js用のソースコードがあったので、forkしてESモジュール化しました。(詳細、エンコード方式 base-122 | POSTD)
「Base122」
オリジナルからencode/decodeのみを抽出し、文字列とUint8Arrayの相互変換に変更。JavaScriptのソースコード、ヒアドキュメントを使った文字列へと変換するための関数encodeJSStringを追加し、encodeJSを追加しました。(Base122.js on GitHub)
Base64変換していたbin2jsを、Base122に変えて実験!
順当にサイズが小さくなっています(左図)。が、GitHub Pagesでは標準となっているgzip圧縮をかけたところ、Base64がBase122より小さくなるという結果に。エンコード方式が複雑なためかgzip圧縮との相性が悪いようです。(計測データとChartBar.jsを使った棒グラフ作図プログラム、on ES-Jam)
そこでESモジュール化したzlib.jsのgzip.js/gunzip.jsを使って、元のデータから圧縮するオプションをbin2jsに追加し再度実験!
左図、元のWASMバイナリデータのgzip圧縮が177KB(元720KB)、Base122で216KB、Base64で248KBとなかなかいい効率です。ただ、右図、この出力をgzip圧縮するとやはりBase64が逆転してしまいます。わずかな差なので、幅広い運用を考えてBase122で統一するのも悪くはなさそう。圧縮オプションを使った場合、12KBあるgunzipするコードをimportするので、もともと圧縮されているファイル、小さいファイル、常時gzip圧縮する環境では圧縮しない方が良いでしょう。
ということで、そこそこ大きいサイズでgzip圧縮されるGitHub Actionsに置く、RubyParserのWASMは、gzip圧縮オプション付きBase64で変換して公開しています。(src on GitHub)
bin2jsで手軽になったWebAssemblyや、Mochi言語を使って実装して比較し、より快適なアプリ環境を目指したいですね。