[技術] malloc的效能

Written on 9:54 上午 by Yu Lai

轉載自強者學弟yuwen的個人板P_yuwen @ cd.twbbs.org

最近因為某些特殊需求,所以必須要使用rainbowtable來輔助,在FreeBSD的ports中有rainbowcrack可以使用,於是就裝了起來,順道測試一下之前抓到的幾個rainbowtable的效率。沒想到一執行rcrack就噴了 = =

只好苦命的來trace code,才發現一個白爛的問題,做這個ports的人在某個function內,因為找不到從linux對應的code,就直接把那段code拔掉 = = 所以return 值亂七八糟的,當然會噴segmentation fault!所以就自己補上那一小段code,本來以為這世界就會再度快樂的運轉。

當然事情不是那麼的簡單,跑沒多久又改噴bus error = = 經過再苦命的trace才找到bug,因為每個rainbowtable去跑一次需要allocate 1G的記憶體,而我拿來測的機器的記憶體只有1G,不過SWAP也有1.5G,不知道為啥就是不會成功。(謎! 板上有長輩知道嗎),所以又找了台有2G RAM的機器來測,發現一樣跑步起來,後來寫了個test code才發現似乎是FreeBSD的malloc的問題。同樣的code,在一樣只有1G的linux上面卻是可以成功。(FreeBSD的libc中的malloc是jemalloc,而linux上面的是ptmalloc2)

My test code:
unsigned char* a = (unsigned char *)malloc(sizeof(unsigned char)*1G);
if(a == NULL) printf("Damn\n");
else printf("Thanks God!\n");
Result:
FreeBSD 6.2-Stable + 1G RAM => Damn
FreeBSD 6.2-Stable + 3G RAM => Damn
Debian etch => Thanks God!

所以就開始尋找替代方案啦,幾個有名的malloc都拿來測試看看,包含下列幾種:
libumem(Sun的),libdlmalloc(FreeBSD開發者弄得),libtcmalloc (google出品)
結果不管換上哪一套,在本來的機器上都可以跑了!!!看來真的是malloc的問題。

解決問題後,就開始想測測看上面這幾套的效能,測試的code如下:
char a[65535];
跑 10 次
random填滿 a[65535], 每個malloc 1~64K
跑 1000000 次
random選一個a[x],如果不是null就free,如果null就
random malloc一塊 1~64K
end 跑
end 跑

結果: tcmalloc > dlmalloc >>>>>>>>>>>>>>>>>>> libumem ~= jemallo ~= ptmalloc
結論: 如果需要大量頻繁的malloc/free,每次都是small allocation的話,應該可以先試試看tcmalloc or dlmalloc

這又帶出一個想法,築夢每次晚間的load都非常重,看了一下code發現其實bbs會頻繁的malloc/free。也許cd.twbbs.org可以改用tcmalloc or dlmalloc看看,也許可以增加一點效率~(ptt是改用dietlibc的malloc)

--
可惜手邊沒有bbs的機器來測, 手好癢阿~ Orz

PS: 最後補一個相關的ref: http://plog.longwin.com.tw/news-unix/2007/03/29/mysql_tcmalloc_2007