LZO說明 摘要 LZO 是一個用 ANSI C 語言編寫的無損壓縮庫。他能夠提供非常快速的壓縮和解壓功能。解壓並不需要記憶體的支持。即使使用非常大的壓縮比例進行緩慢壓縮出的數據,依然能夠非常快速的解壓。LZO 遵循 GNU 的 GPL 使用許可。 介紹 LZO 非常適合進行數據的實時壓縮解壓處理,這 ...
LZO說明
摘要
LZO 是一個用 ANSI C 語言編寫的無損壓縮庫。他能夠提供非常快速的壓縮和解壓功能。解壓並不需要記憶體的支持。即使使用非常大的壓縮比例進行緩慢壓縮出的數據,依然能夠非常快速的解壓。LZO 遵循 GNU 的 GPL 使用許可。
介紹
LZO 非常適合進行數據的實時壓縮解壓處理,這就是說他更關心操作速度,而不是壓縮比例。
LZO 使用 ANSI C 語言編寫,並且壓縮後的數據也被設計為可以跨平臺使用的格式。
LZO 擁有如下的特點:
- 解壓速度很快,並且很簡單;
- 解壓時不需要記憶體支持;
- 壓縮的速度還不錯;
- 壓縮時只需要 64 KiB 的記憶體支持;
- 壓縮比例可以根據需要調節,而這並不影響解壓的效率,提高壓縮比例自然會降低壓縮速度;
- 壓縮包含了很多的壓縮級別,提供很多選擇;
- 提供只需要 8 KiB 記憶體支持的壓縮級別;
- 提供線程安全;
- 提供無損壓縮;
LZO提供多重壓縮,和複原解壓;
設計標準
LZO 以處理速度為原則設計。解壓速度要快於壓縮速度。能夠提供給任何程式實時解壓的功能。LZO1X的解壓是按照 i386 編碼優化的。
事實上,是通過解壓演算法定義的壓縮數據結構,最後採用手工測試數據驗證了這個結構。
效果
在古老的 Pentium 133 的設備上,我們運行了 Calgary Corpus 的測試數據。數據採用了 256 KiB的大小。
LZOxx-N 定義了使用的演算法名稱,N代表壓縮級別。1-9 級別使用 64 KiB 記憶體,他主要提供更快的壓縮速度。99 級別使用 256 KiB 記憶體,提供更大的壓縮比例,但是處理速度依然很快。999 級別是按照壓縮比例優化的演算法,他的壓縮速度很慢,並且使用大量的記憶體,這種級別一般用於生成預壓縮數據。
C 語言版本的 LZO1X-1 演算法要比最快的 ZLIB 壓縮級別,快4-5倍的速度。當然他也在壓縮比例、壓縮時間、解壓時間方便優於 LZRW1-A 和 LZV 這些演算法。
+------------------------------------------------------------------------+ | Algorithm Length CxB ComLen %Remn Bits Com K/s Dec K/s | | --------- ------ --- ------ ----- ---- ------- ------- | | | | memcpy() 224401 1 224401 100.0 8.00 60956.83 59124.58 | | | | LZO1-1 224401 1 117362 53.1 4.25 4665.24 13341.98 | | LZO1-99 224401 1 101560 46.7 3.73 1373.29 13823.40 | | | | LZO1A-1 224401 1 115174 51.7 4.14 4937.83 14410.35 | | LZO1A-99 224401 1 99958 45.5 3.64 1362.72 14734.17 | | | | LZO1B-1 224401 1 109590 49.6 3.97 4565.53 15438.34 | | LZO1B-2 224401 1 106235 48.4 3.88 4297.33 15492.79 | | LZO1B-3 224401 1 104395 47.8 3.83 4018.21 15373.52 | | LZO1B-4 224401 1 104828 47.4 3.79 3024.48 15100.11 | | LZO1B-5 224401 1 102724 46.7 3.73 2827.82 15427.62 | | LZO1B-6 224401 1 101210 46.0 3.68 2615.96 15325.68 | | LZO1B-7 224401 1 101388 46.0 3.68 2430.89 15361.47 | | LZO1B-8 224401 1 99453 45.2 3.62 2183.87 15402.77 | | LZO1B-9 224401 1 99118 45.0 3.60 1677.06 15069.60 | | LZO1B-99 224401 1 95399 43.6 3.48 1286.87 15656.11 | | LZO1B-999 224401 1 83934 39.1 3.13 232.40 16445.05 | | | | LZO1C-1 224401 1 111735 50.4 4.03 4883.08 15570.91 | | LZO1C-2 224401 1 108652 49.3 3.94 4424.24 15733.14 | | LZO1C-3 224401 1 106810 48.7 3.89 4127.65 15645.69 | | LZO1C-4 224401 1 105717 47.7 3.82 3007.92 15346.44 | | LZO1C-5 224401 1 103605 47.0 3.76 2829.15 15153.88 | | LZO1C-6 224401 1 102585 46.5 3.72 2631.37 15257.58 | | LZO1C-7 224401 1 101937 46.2 3.70 2378.57 15492.49 | | LZO1C-8 224401 1 100779 45.6 3.65 2171.93 15386.07 | | LZO1C-9 224401 1 100255 45.4 3.63 1691.44 15194.68 | | LZO1C-99 224401 1 97252 44.1 3.53 1462.88 15341.37 | | LZO1C-999 224401 1 87740 40.2 3.21 306.44 16411.94 | | | | LZO1F-1 224401 1 113412 50.8 4.07 4755.97 16074.12 | | LZO1F-999 224401 1 89599 40.3 3.23 280.68 16553.90 | | | | LZO1X-1(11) 224401 1 118810 52.6 4.21 4544.42 15879.04 | | LZO1X-1(12) 224401 1 113675 50.6 4.05 4411.15 15721.59 | | LZO1X-1 224401 1 109323 49.4 3.95 4991.76 15584.89 | | LZO1X-1(15) 224401 1 108500 49.1 3.93 5077.50 15744.56 | | LZO1X-999 224401 1 82854 38.0 3.04 135.77 16548.48 | | | | LZO1Y-1 224401 1 110820 49.8 3.98 4952.52 15638.82 | | LZO1Y-999 224401 1 83614 38.2 3.05 135.07 16385.40 | | | | LZO1Z-999 224401 1 83034 38.0 3.04 133.31 10553.74 | | | | LZO2A-999 224401 1 87880 40.0 3.20 301.21 8115.75 | +------------------------------------------------------------------------+
註解:
- CxB 是塊的數目;
- K/s 是每秒處理 1KB 沒有壓縮的數據的速度;
- 彙編的解壓速度將會更快;
簡單文檔
LZO 是塊壓縮演算法,他壓縮和解壓一個塊數據。壓縮和解壓的塊大小必須一樣。
LZO 將塊數據壓縮成匹配數據(滑動字典)和非匹配的文字序列。LZO 對於長匹配和長文字序列有專門的處理,這樣對於高冗餘的數據能夠獲得很好的效果,這樣對於不可壓縮的數據,也能得到較好的結果。
在處理不可壓縮數據時,LZO 將擴展輸入數據,每1024個位元組最大增加 64 個位元組。
我已經通過類似於 valgrind 這樣的記憶體檢查工具驗證過 LZO 程式,並且也使用了超過千兆位元組的數據,進行各種參數調整,檢查過各種潛在的問題。LZO 目前不存在任何已知 BUG。
各種演算法說明
這裡實現了很多的演算法,但是我希望提供沒有限制的向下相容性,所以以後並不會取消現有的內容。
就像需要對象文件都是相對獨立的,若通過靜態鏈接使用 LZO 庫,只會增加很少的容量(大約幾KiB),以為內只要在真正使用 LZO 功能時這個模塊才會被載入。
1996年3月,我在 newsgroups.comp.compression 和 comp.compression.research 公佈了 LZO1 和 LZO1A。他們主要處理了相容性的問題。LZO2A解壓的速度非常慢,並且也沒有能提供一個較快的壓縮速度。
在我的試驗中可以看到,LZO1B適合處理大量的數據,或者有高冗餘性的數據。LZO1F適合處理小量數據和二進位數據。LZO1X適合各種環境。LZO1Y 和 LZO1Z 跟 LZO1X 很相像,他們能夠在一些環境中達到更好的壓縮比例。
請註意,你有很多的選擇。
使用 LZO 庫
無論數據的大小,使用 LZO 庫的基本功能非常的簡單。我們假設你打算使用 LZO1X-1的演算法處理你的數據。
壓縮
1 include <lzo/lzo1x.h> 2 call lzo_init () 3 通過 lzo1x_1_compress () 壓縮你的數據 4 編譯連接 LZO 庫
解壓
1 include <lzo/lzo1x.h> 2 call lzo_init () 3 通過 lzo1x_decompress () 解壓數據 4 編譯連接 LZO 庫
在源碼包的 examples/simple.c 有完整的範例代碼。也可以查看 LZO.FAQ 獲得更多內容。
原始文件:
LZO FAQ
-
我不想閱讀文檔,指向知道如何將這個功能添加到我的程式中
有兩個範例:examples/simple.c 和 examples/lzopack.c 提供了簡單使用的方法。
但是最好還是將整個的文檔閱讀完成,會幫助你更好的使用。
-
你能解釋一下各種演算法名稱的含義嗎?
我們用 LZO1X 來舉例說明:
演算法名稱:LZO1X
演算法分類:LZO1
然後提供了很多的壓縮級別:
LZO1X-999 !---------- 演算法分類 !--------- 演算法類型 !!!----- 壓縮級別 (1-9, 99, 999)
LZO1X-1(11) !---------- 演算法分類 !--------- 演算法類型 !------- 壓縮級別 (1-9, 99, 999) !!---- 記憶體級別 (壓縮時所需要的記憶體)
在一個壓縮類型中,不同的壓縮級別和記憶體級別的數據結構是相同的,所以 LZO1X 的解壓方法,能夠適用於 LZO1X-** 對應的所有壓縮演算法。 LZO1 分類:使用嚴格的 BTYE 校驗的 壓縮數據結構 LZO2 分類:使用 bit 位移方式,解壓速度比較慢。 -
為什麼有這麼多的演算法?
由於很多的歷史版本,而我希望能夠提供良好的向下相容性,所以擁有這麼多演算法。不必擔心整個庫的大小問題,使用其中一種演算法,只會給你的程式添加很少的幾個 KiB。
如果你只是希望給你的程式添加一個簡單的壓縮功能,你可以查看 miniLZO 部分,在 minilzo/README.LZO 中,可以查看更纖細的信息。
-
我應該使用哪種演算法?
LZO1X 在很多情況下都是一個比較好的選擇。所以,追求速度可以使用 LZO1X-1,生成預壓縮文件可以使用 LZO1X-999,如果你有很多的記憶體,可以使用 LZO1X-1(11) 或者 LZO1X-1(12)。
當然這裡有很多的選擇,你可以根據自己的需要進行選擇。也可以嘗試一下 LZO1Y 或者 LZO1F 等等。
-
在解壓的時候,每種方式有什麼區別?
我們還是使用 LZO1X 作為範例來說明:
- lzo1x_decompress
他能夠提供較快的解壓速度,這是一個標準的解壓方式。但是他不提供附加的相關數據安全檢查,他預設處理的數據是完成的壓縮後數據。如果數據由於各種原因損壞,例如硬碟損壞或者傳輸過程中的錯誤而破損,那麼他可能直接產生嚴重錯誤,而終止你的程式。
- lzo1x_decompress_safe
這是一個安全的解壓方式,但是他會慢一些。他會捕捉解壓中的數據問題,並且返回相關的錯誤信息,而避免產生嚴重錯誤。
- lzo1x_decompress_asm
一個類似於 lzo1x_decompress 的方式,但是是通過彙編實現的。
- lzo1x_decompress_asm_safe
一個類似於 lzo1x_decompress_safe 的方式,但是是通過彙編實現的。
- lzo1x_decompress_asm_fast
類似於 lzo1x_decompress_asm 方式,但是能夠提供更快的速度。為了提高速度,他會在解壓後的數據結尾添加 3 BYTE 的數據。因為這種方式按照 32 bit 作為一個單位進行數據處理。
當你從一個記憶體塊解壓數據到另外一個記憶體塊,需要多提供 3 BYTE 的數據存儲空間。如果你要直接解壓一個視頻內容,不要使用這種方式,因為最後添加的 3 BYTE 的內容會被當成顯示內容處理。
- lzo1x_decompress_asm_fast_safe
這是一個 lzo2x_decompress_asm_fast 的安全版本。
這裡請註意如下內容:
- 當使用安全類型的解壓方式時,要通過 dst_len 參數說明 dst 參數可以放置的數據最大容量。
- 如果你希望確認你的壓縮後的數據是安全的,請使用 MD5 之類的檢查,當然若使用安全類型的方式不需要這個檢查。因為在安全方式中,任何錯誤都回被捕捉並返回。
- 彙編版本只能在 i386 的架構中使用,具體的信息可以查看 asm/i386/OOREADME.TXT 文件中查看相關內容。
- 你可能需要測試一下彙編版本是否比C語言版本速度更快,有些編譯器能夠完成很好的優化工作,使得C語言版本能夠工作的很好。
- lzo1x_decompress
-
優化處理了哪些東西?
壓縮採用了啟髮式方法,他們有時記錄信息,這不能提高壓縮比例。優化去處了這些不必要的信息,來提高解壓速度。
在解壓時,同樣也不處理這些可能記錄壓縮內容變化的內容。壓縮後的數據在一些 bit 中會重新排列,這不會引起壓縮後數據的容量變化。
經過優化處理以後,解壓速度可以提升 1-3%。優化沒有更多的效果提升了。
-
我需要更快的解壓速度
在很多 RISC 處理其中(例如MIPS),針對 32-bit WORD 的傳送速度要快於 BYTE,這能夠有效的提高解壓速度。所以在驗證完其他部分工作正常後,你可以在LZO1X 和LZO1Y 兩種演算法的解壓時,採用 LZO_ALIGNED_OK_4 來提高效率。變更 config.h 中相關的內容,並且重新編譯所有東西,以使用它。
在 i386 的架構中,你可以嘗試使用彙編版本。
-
我如何在壓縮或者解壓時減少記憶體的使用?
如果你能夠聰明的控制數據的範圍,那麼你可以在解壓縮的時候,使用壓縮使用的記憶體。這樣能夠有效的移除保存壓縮後的數據的記憶體。這需要你瞭解對於可執行包裹的基礎瞭解。
當然你也可以部分的重用壓縮時的BUFF
在 examples/overlap.c 的範例中,可以看到更詳細的內容。
-
我能獲得一個關於預壓縮的相關指導嗎?
在演算法 LZO1X-999 的情況下:
預壓縮步驟:
1 call lzo_init() 2 call lzo1x_999_compress () 3 call lzo1x_optimze () 4 對於壓縮後的數據做一個 32長度的 MD5 5 將壓縮後的數據和對應的MD5保存在一個文件中 6 如果你還不放心,可以現在進行一次解壓驗證
解壓步驟:1 call lzo_init () 2 裝載你的壓縮數據和對應的 MD5 3 通過 MD5 驗證你的壓縮後的數據 4 解壓
可以在 examples/precomp.c 和 examples/precomp2.c 的代碼中查看到更詳細的範例。 -
壓縮以後,我的數據會增長多少?
LZO 對於不可壓縮的數據,會增加一點容量。我一直沒有計算過精確的數字,但是下麵列出了最浪費的情況下的公式:
壓縮演算法:LZO1,LZO1A,LZO1B,LZO1C,LZO1F,LZO1X,LZO1Y,LZO1Z
1 output_block_size = input_block_size + (input_block_size / 16) + 64 + 3
這大約是原始數據的106%。壓縮演算法:LZO2A
1 output_block_size = input_block_size + (input_block_size / 8) + 128 + 3