天天看點

[MySQL 學習] zlib庫相關結構和函數

以下主要是閱讀zlib庫時,對庫函數的注釋的翻譯,也是為了幫助了解zlib在innodb壓縮表中的應用

這裡隻考慮了innodb用到的函數,其他的具體參考zlib.h檔案,裡面的注釋寫的非常詳細

————————-

1.主要用到的結構體是z_stream,定義在檔案zlib/zlib.h中,我們需要去定義的字段包括

bytef    *next_in

輸入的源字元串

uint     avail_in

輸入源字元串長度,當avail_in下降到0時,必須更新next_in和avail_in

bytef    *next_out

輸出字元串

uint     avail_out

在next_out中的可用空閑空間,當avail_out下降到0時,必須更新next_out

alloc_func zalloc

記憶體配置設定函數,innodb裡對應的函數指針是page_zip_zalloc

如不指定需要設定為null

free_func  zfree

記憶體釋放函數,innodb裡對應函數指針為page_zip_free

voidpf     opaque

會被作為參數傳遞給zalloc和zfree,在innodb裡使用的是mem_heap.

2.壓縮函數(隻涉及到innodb中的調用)

a.deflateinit2(strm, level, method, windowbits, memlevel, strategy)

參數

@1, z_stream對象

@2,壓縮級别

@3,值為z_deflated,目前唯一的defalte壓縮方法,用于以後擴充

@4,視窗比特數,範圍在8~15,更大的值意味着消耗更多的記憶體來獲得更好的壓縮效果,如果使用deflateinit來初始化的話預設值為15

windowbits也可以在-8~-15間指派,用于raw deflate(不了解?),這時候使用-windowsbits來決定視窗大小,deflate()會生成raw deflate data,沒有zlib頭和尾,并且也不會去調用adler32

當使用gzlib編碼時,windowsbits也可以設定為大于15,但跟zlib的檔案格式會有很大的不同。

在innodb中值為univ_page_size_shift,值為14(如果page size為預設16k的話)

@5,memlevel用于指定配置設定多少記憶體用于内部的壓縮狀态,值為1将使用最小的記憶體但更慢并降低壓縮比;memlevel值為9時,會使用最大記憶體來獲得最快的速度。預設值為8,在innodb裡使用的值為max_mem_level,deflate需要的記憶體為:

(1 << (windowbits+2)) +  (1 << (memlevel+9))

@6,用于調整壓縮算法

包括以下值:

z_default_strategy, 用于普通資料

z_filtered,用于由filter(或者稱為predictor)生成的資料.過濾的資料包含很多小的随機資料。這種情況下,壓縮算法能夠獲得更好的壓縮效果。該選項可以強制更多的哈夫曼編碼和更少的字元比對。有時候可以作為z_default_strategy和z_huffman_only的折衷。

z_huffman_only,用于強制哈夫曼編碼(不做字元比對)

z_rle,限制比對長度為1(run-length encoding),用于設計的和z_huffman_only一樣快速,但對png圖檔類型會獲得很好的壓縮效果

z_fixed,阻止使用動态哈夫曼編碼,進而允許獲得更簡單的解碼

strategy參數隻影響壓縮比,而不會影響到壓縮輸出的正确性,是以沒有正确的設定也不要緊。

b.deflate(strm, flush)

deflate盡可能的進行資料壓縮,如果輸入緩存變空或者輸出緩沖變慢了才會停止。除了需要強制重新整理,可能會引入一些延遲(讀取輸入資料,而不産生輸出)

-從next_in開始壓縮更多的資料,并更新相應的next_in和avail_in。如果無法處理所有的輸入(因為在輸出緩存中沒有足夠的空間),next_in和avail_in會在目前點更新并在下次調用delfate時從目前點重新開始。 -從next_out開始産生更多的輸出,并更新相應的next_out和avail_out。當flush參數為非0值時,上述行為會被強制執行,強制頻繁的重新整理會降低壓縮比,是以該參數應該隻在需要的時候才去設定它(例如互動式應用)。即使沒有設定flush,也需要提供一些輸出。

在調用deflate函數之前,應用需要确定以上至少有一個行為是可行的(通過提供更多的輸入或消費更多的輸出,并更新相應的avail_in活avail_out)。在調用deflate前,avail_out不可為空。應用能夠在需要時候消費壓縮資料輸出,例如,在輸出緩沖滿時(avail_out==0),或者每次調用deflate函數之後。如果deflate傳回值為z_ok并且avail_out值為0,在清空輸出緩沖後,需要再次調用deflate,因為有可能還有更多未完成的資料。

通常情況下, flush參數被設定為z_no_flush,這允許deflate來決定在産生輸出前積攢多少資料,以獲得更好的壓縮效果。

當flush被設定為:

z_sync_flush,所有pending的輸出被重新整理到輸出緩沖,以位元組邊界對齊,這樣解壓器能夠獲得目前所有可用的輸入資料。(特别是如果有足夠的輸出緩沖,在調用函數後,avail_in值為0)。flush操作可能會降低壓縮效果,是以應該隻在需要使用。在完成目前delfate塊後,随後是一個空的存儲塊,在下個位元組裡有3個bit的留白,随後是4個位元組(00 00 ff ff)

z_partial_flush,所有pending的輸出被重新整理到輸出緩沖,但不以一個位元組邊界對齊,當設定為該值時,所有目前的輸入資料對解壓器而言是可用的。這確定了足夠的位元組按序輸出給解壓器,以在空的固定代碼塊之前完成block

z_block,如果一個deflate塊結束并送出,但輸出不做對其,并且目前塊最多保留7個bits,在下一次deflate塊完成後作為next byte寫入。這種情況下,解壓器可能無法提供足夠的bit去完成資料解壓以提供給壓縮器。這需要下一個block送出後才能完成。

z_full_flush,所有的輸出都被重新整理,所有的壓縮狀态也被重置。這樣如果目前壓縮資料損壞或者需要随機通路時,解壓操作可以從這個點重新開始。太頻繁的使用z_full_flush會驗證的降低壓縮性。

如果deflate傳回并且avail_out值為0,該函數必須再次使用相同的flush參數調用,并預留足夠的輸出空間,直到flush完成(defalte傳回非0的avail_out)。當使用z_full_flush或z_sync_flush時,確定avail_out大于6以避免重複的flush标記。

z_finish,pending的輸入被執行,pengding的輸出被重新整理,如果有足夠的輸出空間時,deflate傳回值為z_stream_end。如果deflate傳回z_ok,該函數必須再次調用一次。在傳回z_stream_end之後,唯一可以進行的操作就是deflatereset或者deflateend。 如果所有的壓縮可以在單獨一步完成時,z_finish可以在defalteinit後立即使用。這種情況下,avail_out的值最少為deflatebound傳回的值。這樣deflate才能確定傳回z_stream_end。

deflate()會在strm->adler上設定目前所有輸入的adler32 checksum值;另外也可能更新strm->data_type值(如果能夠猜測輸入資料的類型,z_binary或者z_text)。

c. deflateend (strm)

所有動态配置設定的資料結構都被釋放掉,并抛棄所有未完成的輸入,也不會重新整理任何pending的輸出。

成功時傳回z_ok,失敗時傳回z_stream_error

d.inflateinit2(strm, windowbits)

用于初始化解壓z_streamp

跟deflateinit2類似,在調用該函數之前,同樣需要先初始化next_in, avail_in, zalloc, zfree 以及 opaque

注意解壓時提供的windowbits不能比壓縮時的windowbits大,否則在解壓時inflate會傳回錯誤z_data_error。

e.inflate(strm, flush)

inflate與deflate相反,根據strm盡可能的解壓資料。

flush參數可以是z_no_flush, z_sync_flush, z_finish,z_block, 或者 z_trees。z_sync_flush要求infalte盡可能的重新整理到輸出緩沖。z_block要求在擷取下一個deflate 塊的邊界inflate需要停止。當解碼zlib或gzip格式時,這會導緻infalte在壓縮資料頭部和在第一個block之前會立刻傳回。

z_block選項有助于在append或組合defalte stream是。inflate在傳回時會設定strm->data_type為從strm->next_in中最後一個位元組中未使用的bit數字。如果inflate正在解碼最後一個block,值為64;如果在解碼end-of-block code或者解碼完整的頭部

z_trees行為和z_block類似,但它也會在每次到達一個deflate塊頭的尾部,在該塊上任何實際需要解碼的資料之前傳回。這允許調用者決定deflate塊頭的長度,用于随後在一個deflate塊中的随機通路。當到達deflate塊頭尾部時,inflate傳回,并設定strm->data_type值為256.

infalte()應該被反複調用,直到其傳回值為z_stream_end或者傳回一個錯誤。然而,如果所有的壓縮操作可以單獨一個步驟來完成(隻調用一次inflate),flush應該被設定為z_finish。這種情況下,所有pending的輸入被處理,所有pending的輸出被重新整理;avail_out必須足夠大,來存儲解壓資料。z_finish也許不是必須的,但他可以用來告訴inflate去使用更快的方法來完成一次inflate調用。z_finish也告訴inflate如果stream完成了,無需維護一個滑動視窗,這減少了inflate的記憶體占用。如果stream沒有完成,或者由于沒有提供全部的stream,或者沒有提供足夠的輸出空間,就會配置設定一個滑動視窗,inflate可以被再次調用去完成操作(就像使用z_no_flush那樣)

f.inflateend(strm)

釋放所有動态配置設定的記憶體

繼續閱讀