LZMA徹底解説:原理から実運用、最適設定まで(エンジニア向け深堀コラム)

はじめに — LZMAとは何か

LZMA(Lempel–Ziv–Markov chain Algorithm)は、高圧縮率を目指した可逆データ圧縮アルゴリズムです。ロシアのプログラマ Igor Pavlov により開発され、7‑Zipアーカイバで広く知られるようになりました。LZMAは圧縮率が高く、特に大きな辞書サイズを使えるため繰り返しや長距離の類似性を持つデータに強みがあります。一方で、圧縮時のメモリ使用量や処理時間が大きくなる傾向があるため、運用ではトレードオフを理解した上でパラメータを決めることが重要です。

歴史とエコシステム

LZMAは Igor Pavlov によって設計され、7‑Zip(オープンソースのアーカイバ)の核として採用されました。後に LZMA2 として仕様改善が行われ、XZ Utils(.xz 形式)などのツールチェーンで採用され、Linuxディストリビューションや組込み用途でも見かけるようになりました。LZMA SDK としてライブラリが公開されており、さまざまな言語/プラットフォームで実装が存在します。

アルゴリズムの概要(高レベル)

LZMA は主に以下の要素で構成されます。

  • バックリファレンス(LZ77スタイル)のマッチ検出:過去のデータから最長マッチを見つけ、(距離, 長さ)の形で出力。
  • リテラル(非マッチのバイト)とマッチの二項モデル:リテラルは文脈ベースのモデルで符号化され、マッチ/リテラルの選択もモデル化される。
  • レンジコーダ(Range coder):算術符号化に基づくエントロピー符号化器を使用し、確率分布に基づいてビット列を効率的に出力する。
  • 複数の確率モデルと状態遷移:文字列の文脈(直前のバイトや位置)に応じた確率推定で圧縮効率を高める。

これらを組み合わせることで、LZMAは特に長距離の一致や複雑な文脈依存性を捉える際に高い圧縮率を示します。

主要パラメータと意味

LZMA の動作はいくつかの重要パラメータで制御できます。実務で触ることの多い主要なものを解説します。

  • 辞書サイズ(Dictionary size): 圧縮が参照できる過去データの大きさ。値を大きくすると長距離の一致を利用できるため圧縮率が向上することがあるが、圧縮時・展開時のメモリ消費が増える。
  • lc, lp, pb(リテラル/位置コンテキストビット): リテラルの文脈モデルを構成するビット数で、文字の高次ビットや位置情報を文脈として扱う。これらを適切に設定することで特定のデータ種(テキストやバイナリ)で効果が出る。
  • アルゴリズム設定(プリセット/プリセットレベル): 7‑Zip や xz では -0 から -9 のようなプリセットがあり、高い値ほど圧縮率優先(その分遅くメモリを多く使う)。

圧縮と展開の性能特性

一般的な性質として、LZMAは「圧縮は遅く・メモリを多く使うが、展開は比較的高速でメモリは中程度」という傾向があります。これはエントロピー符号化(レンジコーダ)や複雑なモデル更新が圧縮側で重くなるためです。実運用では次の点に注意します。

  • 圧縮時のメモリは辞書サイズとマッチファインダの実装に依存する。大きな辞書にすると数十〜数百MiBを必要とすることがある。
  • 展開時のメモリは通常圧縮時より小さいが、辞書を保持するための領域は必要。
  • マルチスレッド化は一筋縄ではなく、単一ストリームを並列化するためにはブロック分割や LZMA2 の仕様を使う必要がある。xz/7‑Zip ではソリッドブロック(複数ファイルを一つの圧縮ストリームで処理)を使うと圧縮率が上がるが、ランダムアクセス性や並列処理とはトレードオフになる。

LZMA2 と xz の位置付け

LZMA2 は LZMA の改良版で、より効率的なストリーミングやマルチスレッド圧縮への対応、より柔軟なバッファ管理などを目的に設計されました。XZ Utils は LZMA2 を使うコンテナ(.xz)形式で、Linux ディストリビューションでのパッケージ圧縮やアーカイブの一部として広く採用されています。XZ はしばしば LZMA(単体)より実運用上扱いやすい機能を提供します(チェックサム、ストリーム結合、メタデータなど)。

実運用での選択基準とチューニング

どの設定を選ぶべきかはユースケース次第です。よくある判断基準を示します。

  • ディスク容量・転送帯域を最優先する場合:最大圧縮(高プリセット、大辞書)を検討。ただし圧縮に時間とメモリがかかる。
  • リアルタイム性や低遅延が重要な場合:圧縮負荷を抑えた低プリセットを選ぶ。展開は多くの場合迅速なので、デバイス側の負荷を最小化できる。
  • 組込み機器やメモリ制約が厳しい場合:辞書サイズを小さくし、LZMAよりもDEFLATEやLZ4など軽量な手法を検討。
  • 並列処理を活用したい場合:ファイルを分割して各チャンクを独立して圧縮する、あるいは LZMA2 を使うツールのマルチスレッド機能を利用する。

実装上の注意点

エンジニアとして LZMA を組み込む際のポイント:

  • ライブラリの選択:公式の LZMA SDK、liblzma(XZ Utils に含まれる)、7‑Zip のコマンドライン、各言語のバインディングなどがある。用途に合わせてライセンスや保守性を確認する。
  • 互換性:.lzma(古い単体フォーマット)、.7z(コンテナ)および .xz(LZMA2 ベース)といった形式の違いを理解し、仕様に合わせたヘッダ処理を行う。
  • メモリ管理:辞書サイズやマッチファインダにより必要メモリが大きくなるため、メモリ割当て失敗時のフォールバックを設ける。
  • パラメータエクスポーズ:運用チームがプリセットや辞書サイズを調整できるようにパラメータを外部設定可能にしておくと柔軟性が増す。

代表的なツールとコマンド例

実務でよく使われるコマンドの一例(ツールによりオプション名は異なる)を簡潔に示します。

  • 7‑Zip(7zコマンド): 高圧縮のアーカイブ作成に使われる。プリセットや辞書サイズを指定可能。
  • xz / unxz: LZMA2 を使った .xz ファイルの圧縮・展開。並列圧縮オプションや圧縮レベルを持つ。
  • liblzma(API): プログラムから LZMA/LZMA2 を利用するための C ライブラリ。

適したユースケースと不向きなケース

向いている場面:

  • ディスク容量や転送バイト数を削減したいアーカイブや配布物。
  • ソースコードやテキスト、類似データが多く含まれるリポジトリの圧縮。
  • ソフトウェア配布パッケージ(RPM/DEB等)で圧縮効率を重視する場合。

向かない場面:

  • リアルタイムストリーミングや高速な圧縮が必要なケース(ログ圧縮や低遅延処理)。
  • 極端にメモリ制約のある組込みデバイスで大きな辞書を使えない場合。

まとめ

LZMA は高圧縮率を実現する強力なアルゴリズムであり、適切にパラメータを調整すれば配布物やアーカイブのサイズを大幅に削減できます。ただし、圧縮時のメモリ・CPU負荷や並列化の難しさ、フォーマット互換性といった運用上の課題もあるため、ユースケースに応じた選択とテストが必須です。特に辞書サイズやプリセットの調整、ソリッド圧縮の有無は実際のデータで評価して決めましょう。

参考文献