天天看點

Lua資料結構 — TString(二)

作者:羅日健

存儲lua裡面的字元串的tstring資料結構:(lobject.h 196-207)

Lua資料結構 — TString(二)

其它結構中也會有l_umaxalign dummy這個東西,來看看l_umaxaliagn:

Lua資料結構 — TString(二)

從字面意思上就是保證記憶體能與最大長度的類型進行對齊,事實上也是做這件事,這裡感覺lua想給各種不同裝置做一種嵌入式腳本,這裡要保證與最大的長度對齊能保證cpu運作高效不會罷工。

tsv才是tstring的主要資料結構:

commonheader:這個是和gcobject能對應起來的gcheader

reserved:保留位

hash:每個字元串在建立的時候都會用有沖突的雜湊演算法擷取哈希值以提高性能

len:字元串長度

哈希是lua裡一個很重要的優化手段,具體的雜湊演算法相關知識在文章最後會補充說明一下,字元串的hast表放在l->l_g->strt中,這個成員的類型是stringtable,我們再來看看stringtable資料結構:(lstate.h 38-42)

Lua資料結構 — TString(二)

stringtable結構很簡單:

hash:一個gcobject的表,在這裡其實是個tstring*數組

nuse:已經有的tstring個數

size:hash表的大小(可動态擴充)

接下來看看stringtable是怎麼動态調整大小的:

Lua資料結構 — TString(二)

每次newlstr的之後,都會判斷nuse是否已經大于table的size,如果是的話就會重新resize這個stringtable的大小為原來的2倍。

Lua資料結構 — TString(二)

在gc的時候,會判斷nuse是否比size/4還小,如果是的話就重新resize這個stringtable的大小為原來的1/2倍。

Lua資料結構 — TString(二)

resize時,需要根據每個節點的哈希值重新計算新位置,然後放到newhash裡。

字元串在哪裡? 看完tstring和stringtable,大家都沒有發現究竟字元串放在哪裡,從記憶體上看其實字元串直接放在了tstring後面,這樣還能省掉一個成員:(lstring.c 56)

Lua資料結構 — TString(二)

在這裡說一點lua的性能問題,雖然不在這個主題的讨論範圍。由上面可以知道lua的字元串是帶hash值的,是以我們拿着一個字元串去做比較、查詢、傳遞等操作都是非常高效的。

但是我們也可以看到每次建立一個新的字元串都會做很多操作,是以這裡不建議頻繁做字元串建立、連接配接、銷毀等操作,最好能緩存一下。

常用的字元串哈希函數比較如下:

Lua資料結構 — TString(二)

其中資料1為100000個字母和數字組成的随機串哈希沖突個數。資料2為100000個有意義的英文句子哈希沖突個數。資料3為資料1的哈希值與1000003(大素數)求模後存儲到線性表中沖突的個數。資料4為資料1的哈希值與10000019(更大素數)求模後存儲到線性表中沖突的個數。

經過比較,得出以上平均得分。平均數為平方平均數。可以發現,bkdrhash無論是在實際效果還是編碼實作中,效果都是最突出的。aphash也是較為優秀的算法。djbhash,jshash,rshash與sdbmhash各有千秋。pjwhash與elfhash效果最差,但得分相似,其算法本質是相似的。

Lua資料結構 — TString(二)

具體js hash算法的沖突性解決和性能上面,我也不懂,具體要找paper看看,但是從資料比較上看,jshash是屬于較好的算法,可也有比jshash算法更好的字元串雜湊演算法。

繼續閱讀