星期五, 1月 19, 2007

到底 reiser4 的 cryptcompress 有沒有用? (上)

幾天前拜讀 Palatis 的這篇 擠壓你的檔案系統, 看完一直很心動想試,但要拿自己的電腦試的話風險可大了,工也不小,到底成效如何也不知道。靈機一動先來做個小實驗。

我覺得平常愛用的 Amarok 啟動速度太慢了,所以就拿它的 library 來踹。找了一下,發現這個 libamarok.so.0.0.0 還蠻大的,約有 5.5MB。

首先把它分別壓成 gz 和 lzo
$ cd ~/tmp
$ cp /usr/lib/libamarok.so.0.0.0 .
$ lzop libamarok.so.0.0.0
$ gzip -1 libamarok.so.0.0.0 -c > libamarok.so.0.0.0.gz

壓完後 size 剩一半,gzip 更小
$ ls -l libamarok.so.0.0.0*
-rwxr-xr-x 1 ranma users 5492864 2007-01-18 15:57 libamarok.so.0.0.0*
-rw-r--r-- 1 ranma users 2227760 2007-01-18 16:11 libamarok.so.0.0.0.gz
-rwxr-xr-x 1 ranma users 2734159 2007-01-18 15:57 libamarok.so.0.0.0.lzo*

因為我要做讀取測試,如果檔案已經 cache 到 RAM 裡就不準了,先得把 cache 清掉才行,怎麼 flush 呢? 我也不曉得,只好寫一個程式來吃記憶體,當 physical memory 空間漸不足時,系統便會放棄 cache。你可以用 free 這個指令來觀察 cache 的行為。eatmem.c 的原始碼如下,MY_RAM_SIZE 須依實際機器的 RAM 調整:
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#define MY_RAM_SIZE (1024*1024*1024)
int main()
{
void *p;
printf("Allocating memory\n");
p = malloc(MY_RAM_SIZE);
if (!p)
return -1;
printf("Filling memory\n");
memset(p, 0x55, MY_RAM_SIZE);
printf("Freeing memory\n");
free(p);
return 0;
}

以下每個實驗前都先要做這件事來確保 cache 被清掉
$ ./eatmem ; sleep 10
Allocating memory
Filling memory
Freeing memory

為什麼要 sleep 10 呢? 因為 eatmem 跑完硬碟好像還會繼續跑個兩三秒,所以大家統一多等十秒再開始。如果有更好的清 cache 方法請不吝告知。

先來看沒壓縮的情況。蝦密! 要兩秒多,難怪啟動慢。
$ time cat libamarok.so.0.0.0 > /dev/null

real 0m2.553s
user 0m0.001s
sys 0m0.038s

來看解 lzo 的表現。不到半秒,我確定有先跑 eatmem。
$ time lzop -d libamarok.so.0.0.0.lzo -c > /dev/null

real 0m0.448s
user 0m0.088s
sys 0m0.013s

解 gz 的表現也差不多。
$ time gunzip libamarok.so.0.0.0.gz -c > /dev/null

real 0m0.444s
user 0m0.171s
sys 0m0.006s

看來壓縮反而會增進硬碟效能理論是真的,不過好像也差太多了,size 小一半速度變五倍! 可能是這個檔被 frag 了,所以讀取速度暴慢,壓縮過剛好避掉這個問題。我後來又拿個 2.4MB 的檔案來測,lzo 只比沒壓縮的稍好一些,分別 0.331s 是 0.224s。如果是拿很小的檔案,有壓縮的就反過來比較慢了。不過我的小檔案測試不是很準,因為沒有把 load cat 和 load lzop 的時間差異考慮進去,下回再找時間來改善吧。