【資料結構重溫】Linux核心中的hash和bucket

來源:互聯網
上載者:User

 雜湊表(Hashtable)又稱為“散置”,Hashtable是會根據索引鍵的雜湊程式碼組織成的索引鍵(Key)和值(Value)配對的集合。Hashtable 對象是由包含集合中元素的雜湊桶(Bucket)所組成的。而Bucket是Hashtable內元素的虛擬子群組,可以讓大部分集合中的搜尋和擷取工作更容易、更快速。
 
雜湊函數(Hash Function)為根據索引鍵來返回數值雜湊程式碼的演算法。索引鍵(Key)是被儲存物件的某些屬性值(Value)。當對象加入至 Hashtable時,它儲存在與對象雜湊程式碼相符的雜湊程式碼相關的Bucket中。當在Hashtable內搜尋值時,雜湊程式碼會為該值產生,並且會搜尋與該雜湊程式碼相關的Bucket。例如,student和teacher會放在不同的Bucket中,而dog和god會放在相同的 Bucket中。所以當索引鍵是唯一從Hashtable擷取元素的效能時表現會較好。Hash的四大優點如下所示。
 
事先不需要排序。
搜尋速度與資料多少無關。
數位簽章的密碼技術保密性(Security)高。
可做資料壓縮(Data Compression),以節省空間的。
 
讀過Linux核心源碼的人可能都會發現,其中並沒有太多複雜的資料結構,作為基礎資料結構的雙向鏈表(list)和基於list實現的hash表佔據了絕大部分資料結構。核心為什麼會大量使用這兩種資料結構呢?圍繞這個問題(主要是hash表),我將以自己的理解揣摩一下其意圖。
 
首先,這兩種資料結構都十分簡單,簡單包括理解起來簡單和使用起來簡單兩方面內容。這也意味著代碼的可讀性和可維護性都比其他複雜的資料結構要好,出現bug的風險也較低。從哲學上來講,這也符合K.I.S.S.條款。
 
其次,核心是一個比較講究效能的軟體,為了程式設計和維護的簡單性而失掉效能,這究竟是不是算得不償失呢?我們是不是應該將天平更加偏向於效能?已經記不起是在哪裡聽說過,很多商業的路由軟體都是基於二叉樹的資料結構來儲存路由項,以求得其路由尋找的時間複雜度為log(n),並且他批評Linux的路由項組織為hash表,致使效能不佳,不適合商業。確實有一定道理,可仔細分析,hash表的效能真的比二叉樹差嗎?二叉樹的插入和刪除某一項的時間複雜度都為log(n);hash表插入和刪除的時間複雜度最好為O(1),最差為O(n),如果選取的表項(m)足夠多,且hash函數足夠好的話,其時間複雜度為O(n/m)(當m<=n時)。當m > n / log(n)的時候,hash表的平均表現就比二叉樹要好;且當m>=n時,其時間複雜度趨近於O(1)。m的值可以做成可調整的,這也正顯示了核心的可定製性。不過,不要盲目樂觀,這一切都是以一個足夠好的hash函數為前期的。
 
如何判定一個hash函數的好壞呢?
 
hash的中文意思是“散列”,可解釋為:分散排列。一個好的hash函數應該做到對所有元素平均分散排列,盡量避免或者降低他們之間的衝突(Collision)。有必要再次提醒大家的是,hash函數的選擇必須謹慎,如果不幸所有的元素之間都產生了衝突,那麼hash表將退化為鏈表,其效能會大打折扣,時間複雜度迅速降為O(n),絕對不要存在任何僥倖心理,因為那是相當危險的。曆史上就出現過利用Linux核心hash函數的漏洞,成功構造出大量使hash表發生碰撞的元素,導致系統被DoS,所以目前核心的大部分hash函數都有一個隨機數作為參數進行摻雜,以使其最後的值不能或者是不易被預測。這又對 hash函數提出了第二點安全方面的要求:hash函數最好是單向的,並且要用隨機數進行摻雜。提到單向,你也許會想到單向散列函數md4和md5,很不幸地告訴你,他們是不適合的,因為hash函數需要有相當好的效能。
 
一籌莫展了吧?誰叫你又想閉門造車了!還是看看前輩們是如何做的,充分發揚拿來主義的精神,我又稱這種做法為“不戰而驅人之兵”,這難道不是兵家之上上策嗎?Linux核心裡面用的jhash是一個久經考驗,並被實踐證明經得起考驗的hash函數,可以CPMS(Copy Paste Modify Save)之。Jhash的作者Bob Jenkins在其網站上還公布了諸如針對能預知的資料進行hash的hash函數--完美(perfect)hash函數等一系列其他hash函數,看客們可以選擇之,如果有興趣繼續鑽研,也可以踏在他們的肩膀上。
 
bucket的英文解釋:
Hash table lookup operations are often O(n/m) (where n is the number of objects in the table and m is the number of buckets), which is close to O(1), especially when the hash function has spread the hashed objects evenly through the hash table, and there are more hash buckets than objects to be stored.
可以這樣理解 。
一個HASH的結果所對應的地址可存放兩個BUCKET。可解決HASH衝突。
要存資料時,第一次HASH到這裡,在第一個BUCKET存放一個資料。
要存資料時,當第二次因某些原因HASH到這裡時,在第二個BUCKET存放另一個資料。
 
linux的hash函數hash_long等,用了golden ratio來計算。因為桶(bits)的數量需要由hash函數和對衝突的期望來決定,那麼對於hash_long這樣的hash函數,我們怎麼確定桶的數量呢?
一般情況下都是自己根據資料特性來考慮使用的 hash 演算法,不是千篇一律咬死一個不放
比如存放 IP 位址的 hash table,用一個 65536 的桶就很好,把 IP 的後 16bit 作為 key
這種方法絕對比 hash_long、jhash 等函數的碰撞率低。
其實就是這個界和效能的折中。我可以取我問題空間的最大值。這樣肯定能保證索引值分散。但是這樣會浪費很多空間。然而取得太小,又影響尋找效率。感覺還是要在實驗中進行測試。而且個人覺得,hash比其他搜尋的資料結構靈活的地方就是它的可定製性。可以根據具體情況調整,以達到最優的效果

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.