DPDK Hash Library原理(學習筆記)

2022-07-21 20:57:23 字數 3248 閱讀 6026

本文主要翻譯至dpdk的官方程式設計指南,在谷歌翻譯的基礎上根據自己的理解做了一些修改。網上搜尋的很多中文翻譯大多是翻譯後直接黏貼上來,有時候連語句都讀不通。希望本文能夠對你有所幫助。

dpdk提供了乙個雜湊庫,用於建立用於快速查詢的雜湊表。雜湊表是一種資料結構,它經過優化,用於搜尋由唯一鍵標識的一組雜湊條目。為了提高效能,dpdk雜湊要求所有鍵在建立雜湊時具有相同的位元組數。

雜湊表的主要配置引數有:

雜湊表還允許配置一些底層實現相關引數,如:

雜湊庫的主要方法有:

除了上述基本方法之外,雜湊庫api還提供了一些更高階的方法來查詢和更新雜湊表:

api還包含乙個方法允許使用者批量查詢條目,這比單個條目查詢效能更高,查詢函式在執行當前操作時預取下乙個條目,這極大地降低了記憶體訪問導致的效能開銷。

使用者可以使用單獨的表來管理與每個鍵關聯的實際資料,該錶記錄了雜湊的條目數和每個條目的位置,如以下各節所述的「流分類」用例所示,使用者也可以儲存實際資料在雜湊表本身中。

在l2/l3**示例中,程式根據包的五元組資訊在雜湊表中查詢對應的流,再決定要將包**到哪個埠。當然,這個表也可以用於更複雜的特性,並提供許多可以在包和流上執行的其他功能和操作。

雜湊庫可以在多程序環境中使用。 唯一的只能在單程序模式下使用的函式是rte_hash_set_cmp_func(),該函式用於設定乙個自定義的比較函式,由於該函式被分配給當前程序的函式指標(因此在多程序模式下不支援)。

雜湊庫支援多執行緒,並且使用者可以在雜湊表建立時通過設定適當的標誌來指定所需的操作模式。 在所有操作模式下,查詢都是執行緒安全的,這意味著可以從多個執行緒同時呼叫查詢。

對於併發寫入和併發讀寫,以下標誌值定義了相應的操作模式:

通過額外的標誌來啟用此功能(預設情況下未設定)。設定(rte_hash_extra_flags_ext_table)時(在極不可能的情況下,由於雜湊衝突過多而導致無法插入鍵盤),雜湊桶將使用鍊錶進行擴充套件,以插入這些失敗的鍵。 對於插入雜湊表的鍵個數能達到容量的100%且不能容忍任何鍵插入失敗(即使很少)的工作負載(例如,電信工作負載),此功能非常重要。 請注意,啟用「無鎖讀寫併發」標誌後,使用者需要呼叫「 rte_hash_free_key_with_position」 api才能釋放空儲存桶和已刪除的鍵,以保持100%的容量保證。

雜湊表有兩個主要的表:

雜湊庫使用cuckoo雜湊演算法來解決衝突。對於任何輸入鍵,都有兩個可能的桶(主和備)用來將該鍵儲存在雜湊表中(最終只會存在主或備中的一處),因此在查詢鍵時僅需要檢查這兩個儲存區中的條目。雜湊庫使用雜湊函式(函式可配置)將輸入鍵轉換為4位元組雜湊值。使用部分鍵雜湊[partial-key],從雜湊值中獲取桶索引和2位元組簽名。

一旦桶被標識後,鍵添的加、刪除和查詢操作的範圍將縮小到這兩個桶中的條目(很有可能條目位於主儲存桶中)。

查詢示例:

首先,計算雜湊值並得到2位元組簽名和主桶的索引。如果簽名儲存在此處(很有可能),我們將其鍵與提供的鍵進行比較,如果匹配,則返回其儲存位置和/或與該鍵關聯的資料。如果簽名不在主桶中,則在第二個桶(備桶)中查詢,並執行相同的步驟。如果兩者都不匹配,則該鍵不在表中,將返回負值。

新增示例:

像查詢一樣,主桶和備桶也得​​到了識別。如果主儲存桶中有乙個空條目,則將簽名儲存在該條目中,並將鍵和資料(如果有)新增到第二個表中,並將第二個表中的索引儲存在第乙個表的條目中。如果主桶中沒有空間,則將該桶上的條目之一推送到其備桶位置,然後將要新增的鍵插入其位置。為了知道被驅逐條目的替代儲存桶在**,使用了一種稱為部分鍵雜湊[partial-key]的機制。如果備桶中有空間,被逐出的條目將儲存在其中。如果沒有,則重複相同的過程(其中乙個條目被推送),直到找到乙個空條目。請注意,儘管第乙個表中有條目移動,但第二個表卻沒有被觸及,這將對效能產生很大影響。

在極少數情況下,經過一定數量的移位後找不到空條目,則認為無法新增鍵(除非設定了可擴充套件桶標誌,在這種情況下桶被擴充套件以插入鍵, 稍後會說明)。 如果鍵是隨機的,此方法將使使用者獲得90%以上的表利用率,而不必刪除任何儲存的條目(例如使用lru替換策略)或分配更多的記憶體(可擴充套件的儲存桶或重新雜湊)。

刪除示例:

與查詢類似,該鍵在其主桶和備桶中進行搜尋。 如果找到了鍵,則將該條目標記為空。 如果雜湊表配置為「刪除時無釋放」或「無鎖讀/寫併發」,則鍵的位置不會釋放。 在讀者不再引用該位置之後,使用者有責任釋放該位置。

設定rte_hash_extra_flags_ext_table標誌後,雜湊表實現仍使用相同的cuckoo雜湊演算法將鍵儲存到第一表和第二表中。但是,在極少數情況下,在達到一定數量的布穀鳥移位之後還是無法插入鍵,此鍵的備桶將擴充套件帶有額外桶的鍊錶,並且該鍵將儲存在此鍊錶中。

在查詢某個鍵的情況下,如前所述,在主、備桶中查詢都沒有匹配項,則會在擴充套件桶(額外桶的鍊錶)中逐一查詢可能的匹配項,如果沒有匹配項,則認為該鍵不在表中。

刪除方法與未設定rte_hash_extra_flags_ext_table標誌的情況基本相同,除了以下這點:如果從任何桶中刪除了乙個鍵並建立了乙個空位置,則與此桶相關聯的擴充套件桶中的最後乙個條目將被移入該空位置,從而縮短鍊錶。

如上所述,在cuckoo雜湊實現裡會將條目推入備桶位置, 因此,隨著使用者向雜湊表新增條目的增多,其在桶中的分布將發生變化,其中大多數字於主桶位置,少數字於備桶位置,隨著條目增加,備桶位置將增加。 此資訊非常有用,因為隨著更多條目被逐出到備桶位置,效能可能會降低。

請參閱下表,其中顯示了隨著表利用率的提高而產生的條目分布示例。

例1:使用jhash演算法在帶有1024個隨機條目的示例表測量條目分布

例2:使用jhash演算法,通過具有100萬隨機條目的示例表測量條目分布

注:表中的值是使用隨機鍵和jhash的平均最大表利用率。

流分類用於將每個輸入資料報對映到它所屬的連線/流。該操作是必需的,因為每個輸入資料報的處理通常是在它們的連線上下文中完成的,因此,將同一組操作應用於來自同一條流的所有資料報。

使用流分類的應用程式通常要管理流表,每條流在此表中都有與其相關聯的條目。流表條目的大小是由應用程式指定,典型值為4、16、32或64個位元組。

dpdk雜湊提供了一種通用方法來實現應用程式的流分類機制。給定乙個實現為陣列的流表,應用程式應建立乙個條目數與流表相同的雜湊物件,並且雜湊鍵大小設定為所選流鍵(如五元組)的位元組數。

應用程式側的流表操作如下所述:

Traceroute原理學習

traceroute 可以讓我們看到 ip資料報從一台主機傳到另一台主機所經過的路由。曾經介紹過 ip記錄路由的選項 rr,為什麼不使用這個選項而另外開發乙個新的應用程式 traceroute呢?原因有三 其一,並不是所有的路由器都支援記錄路由這個選項 其二,記錄路由一般是單向的選項,傳送端設定了該...

Spring原理學習

簡介 spring 框架是乙個分層架構,由 7 個定義良好的模組組成。spring 模組構建在核心容器之上,核心容器定義了建立 配置和管理 bean 的方式。組成 spring 框架的每個模組 或元件 都可以單獨存在,或者與其他乙個或多個模組聯合實現。每個模組的功能如下 核心容器 核心容器提供 sp...

Mysql 原理學習

7 27 2 併發控制和鎖的概念 併發會 有可能產生 資料髒讀 多個操作修改 同乙個資料時,產生髒資料。解決併發問題的解決方案 鎖的機制 1 共享鎖 2 排它鎖 讀鎖和寫鎖 select 時 加讀鎖,其他的select 操作可以讀取,但是不能修改 update 時 加寫鎖,其他的 操作不了。鎖的粒度...