Reiser4のLZ4圧縮プラグインを書いたように

画像



この[ 1、2 ]について十分な情報があり、それを繰り返す理由がないので、Reiser4が何であり、何を食べているのかについては説明しません。 したがって、2010年にReiser4を試してみることにしましたが、透明圧縮とテールパッケージの使用に問題があるため(現在解決されているフラッシュ手順に問題があることがわかったため[ 3 ])、ReiserFSに切り替えました。 2013年に、この問題が解決されたことがわかり[ 4 ]、Reiser4(固定システムのLZO1、圧縮なしのラップトップ)に戻りました。 しばらくして、「超高速圧縮アルゴリズム」LZ4に関するニュースと、IllumosコミュニティがZFSでサポートを追加したという事実を思い出しました。 それから私は、「Reiser4がLZ4をサポートしていたら素晴らしいだろう」という考えに立ち会いました。 それで、私はそれをReiser4に「アタッチ」し始めました。



最初に、ccreg40プラグインコードを調べました(ご存じのとおり、Reiser4にはプラグイン構造があります)。 それはすべて、ファイルreiser4_compression_id列挙を持つfs / reiser4 / plugin / compress / compress.hで始まります。

typedef enum { LZO1_COMPRESSION_ID, GZIP1_COMPRESSION_ID, LAST_COMPRESSION_ID, } reiser4_compression_id;
      
      





圧縮アルゴリズムの識別番号を識別します(デフォルトでは、LZO1とGZIP1が使用可能です)。 リストの最後はLAST_COMPRESSION_IDです。これは、アルゴリズムと関連関数に関する情報を含むさまざまなテーブルのサイズを決定するために必要です。



ファイルfs / reiser4 / plugin / compress / compress.cに進みます。このファイルでは、すでに関数を直接記述しています。 7つの主要機能のみ:





alloc()/ free()関数について説明します。 それらが受け入れる引数の1つは、tfm_action型の引数です。 tfm_actionは、ヘッダーファイルfs / reiser4 / plugin / compress / compress.h (reiser4_compression_idと同じ構造を持ちます)に記述されている列挙です。TFMA_READとTFMA_WRITEの2つの要素があります。

 typedef enum { TFMA_READ, /* decrypt, decompress */ TFMA_WRITE, /* encrypt, compress */ TFMA_LAST } tfm_action;
      
      





したがって、読み取り時または書き込み時に、瞬間、関数呼び出しを決定することができます。 一部のアルゴリズムでは、圧縮解除のために追加のメモリが必要になるため、適切な量のメモリを正しく割り当てます。 たとえば、GZIP1アルゴリズムには追加のメモリが必要であるため、それを割り当てますが、LZO1 / LZ4アルゴリズムはそれを必要とせず、割り当てもしません。



すべてが同じcompress.cファイル( compression_plugins配列の説明)で終わります。ここで、プラグインのタイプ、その識別番号、ヘッダー、関数などを示します。

  [LZ4_COMPRESSION_ID] = { .h = { .type_id = REISER4_COMPRESSION_PLUGIN_TYPE, .id = LZ4_COMPRESSION_ID, .pops = &compression_plugin_ops, .label = "lz4", .desc = "lz4 compression transform", .linkage = {NULL, NULL} }, .init = lz4_init, .overrun = lz4_overrun, .alloc = lz4_alloc, .free = lz4_free, .min_size_deflate = lz4_min_size_deflate, .checksum = reiser4_adler32, .compress = lz4_compress, .decompress = lz4_decompress }
      
      







次に、LZ4コードで変更した内容について説明します。 まず、Microsoft Visual Studio(MS VSコンパイラを使用してLinuxカーネルをビルドするかもしれませんが、明らかにこれは近い将来にないでしょう)とC ++(1つのextern“ C”)に関連するすべてのコードを削除しました。 その後、彼はBigEndianシステムの最適化に関連するコードを削除しました。これにより、出力情報がLittleEndianシステムと互換性がなくなり、通常の代わりにスタックメモリを使用できるようになりました(結果はより速くなりますが、カーネル内にあり、そのような自由は無駄になりません)。 最後に、コードからmalloc()/ free()関数を削除し、関数引数のリストにLZ4のニーズに割り当てられたメモリへのポインタを追加しました(alloc()を思い出してください)。



さて、今最も重要なことは、それがすべてどのように機能したかです...率直に言って、ひどく。 LZ4プラグインは、LZO1プラグインよりも動作が遅く、圧縮率が低下しました。 測定は、シングルユーザーモードのライブシステムで実行されました。 測定には、パーティションのマウント解除操作が含まれていました(同期/フラッシュ手順が機能し、ファイルがディスクに完全に書き込まれたため)。 3つのテストが実行されました:ゼロで圧縮されたファイルのディスクへの線形書き込み/読み取り(/ dev / zeroから)、非圧縮ファイルの線形読み取り/書き込み(以前は/ dev / urandomから取得され、メモリ内のtmpfsに書き込まれました)およびLinuxカーネルソースコードの解凍/圧縮バージョン3.9.5。 すべてのテストの中で、LZ4を使用したプラグインは、ゼロのファイルを読み書きする場合にのみ利点を示しました。 他のすべてのテストでは、LZO1は圧縮/解凍速度と最終ファイルサイズの両方でLZ4よりも優れていました。



さらなる研究の過程で(LZ4とlz4cからのフルベンチ対lzop)、LZ4は小さなブロックですべてのプロパティを失い、宣言されたプロパティ[ 5 ]を大きなブロックでのみ表示することがわかりました。たとえば、デフォルトのフルベンチ4MiB lz4c 8MiB。 Eduard Shishkinが言ったように、「4MiBは少し大きい。 LZO1はピースを圧縮し、はるかに小さい..” [ 6 ]



したがって、Reiser4の場合、LZO4よりもLZO1の方が望ましいオプションであることがわかりました。 ちなみに、ZFSでコミュニティによって追加されたLZ4のサポートは、(LZJBの場合と比較して常に)常に現れるとは限らず、LinuxでLZ4をプッシュする試みが失敗することがわかります[ 7 ](使用する機会として)カーネル圧縮またはinitram)の確認。 btrfsのLZ4について... Eduard Shishkinは、btrfs [ 8 ]が何であり、どのように開発されているかを明確に述べました。






Linux 3.9用のパッチReiser4

Reiser4のパッチLZ4

PS関数LZ4_decompress_safe()は少しやり直す必要がありますが、意味をなさないので、私はしませんでした。

reiser4progsのパッチ

[1] habrahabr.ru/post/45873

[2] http://theoks.net/~onekopaka/Reiser4Site/v4.html

[3] marc.info/?l=reiserfs-devel&m=135146138331012&w=2

[4] sourceforge.net/p/reiser4/discussion/general/thread/2bca4f8e

[5] code.google.com/p/lz4

[6] sourceforge.net/p/reiser4/discussion/general/thread/780facb4

[7] lwn.net/Articles/534168

[8] habrahabr.ru/post/108629



All Articles