Hash 的工程優勢: port range 匹配

昨天和朋友聊到 “如何匹配一個 port range”,覺得挺有意思,簡單寫篇散文。

回想起十多年前,我移植并優化了 nf-HiPAC,當時還看不上 ipset hash,后來大約七八年前,我又舔 nftables,因為用它可直接寫多維樹匹配,更早之前,Linux 內核 Hash 路由查找算法被 trie 替代時,我就寫文捧過一番,我是有多么看不上 Hash,似乎任何一棵 Tree 都吊打 hash。

多年以后反思,如果再讓我做同樣的需求,我定會 Hash 做到底,不會再動 Tree 的主意。Hash 實現最簡單,并可隨內存線性擴展,在大多數場景下也不會比 Tree 差,只有純理工科背景且未被工程教訓毒打過的副經理才會拎出 Tree 更好的例外作為替換 Hash 的理由。

匹配 port range,想當然的算法是構建區間查找樹,當年看 Linux 內核 mmap 實現時看到過 Linux 文件映射就是用區間樹實現,所以但凡和區間關聯的,我都會去安利區間樹,也因此當年優化 nf-HiPAC 時也就是選定了它,但在實現過程中遇到了極大的困難,于是我就偷了個懶。

有意思的是,這個偷懶很值得。

我沒有用實際 rule 中的 port range 直接構建區間樹,而將整個 port 空間分為一致 500 個端口一組的等距區間,然后將實際 rule 的 port range 往上蓋,在等距邊界處做 split。比如 rule 的 range 1234~1400,則 1000~1500 等距區間就被分為了 3 部分,這 3 部分作為匹配 1000~1500 后的二級匹配,執行一個線性遍歷就完了。

我當時非常看不起線性遍歷,所以一直耿耿于懷,我當時不知道,幾十以內的線性遍歷其實是無傷遍歷,更何況個位數。巧的是我當時能力不足以讓我繼續優化成 Tree,就保留了 “二分等距區間查找 + 線性遍歷” 的 “拙劣” 實現,沒想到它工作得非常好。

回想起來,這種等距區間分割,讓規則中的 port range 適配它的做法,依然屬于橫豎顛倒,撥云見日。我對這種方法論的掌握已經深入了內心,下意識而為之。

現如今,我連等距區間樹也要扔掉,用 hash 替代等距區間樹,就是另一個新的算法:
在這里插入圖片描述
Hash 相比樹的缺點在于要遍歷沖突鏈表,比如 Linux 內核里的 hlist。假設 hash 算法足夠優秀(沒得說,都不差),hlist 中元素的個數是可隨著內存增加減小的,而樹的操作無論多好的 CPU 始終是 log 級。

雖然 Hash 要額外處理沖突,但樹也不是一步到位的,加上樹的平衡,鎖等復雜操作,在通用軟件場景下,其性價比遠小于 Hash。假設 50000 并發,2000 個 hash bucket,平均只需要遍歷 25 次,而采用二叉樹需要 15 次操作,但算上其插入,平衡操作,是要比 hash 更昂貴的。二叉樹只在更大并發時才凸顯優勢,其操作量隨數據量 log 增長,而線性增長的 hash 操作亦可通過增加內存抵消操作數量。但如若真遇到海量并發,通用軟件本身就成了瓶頸。

確保下面的區域:
在這里插入圖片描述
顯然,x 會隨內存增加向右線性延展,,而 log 曲線 y = α ? log ? 2 x y=\alpha\cdot\log_2{x} y=α?log2?x 則會因 CPU 性能提升而下壓。純算法分析,log 下壓更明顯,但純算法分析,Hash 簡直就是 O(1),所以二者并非簡單的時間空間較勁二選一,而是呼吁架構的改變。

其實說白了就是 Hash 簡單易實現沒 bug,特別是頻繁增刪查的場景,一個反面案例來自 David Miller 對 IPv6 路由查找的 “優化”,惹了不少麻煩(詳見 3.10 內核中 IPv6 的缺陷),要是用 Hash 實現,不可能有這事。

說點形而上。

Hash 和 Tree 實際上代表了計算在空間和時間分別展開的兩個方向,Hash 的 O(1) 約束下,1 倍的規模增量可帶來1 次操作增量,需要 1 倍的內存來抵消這 1 次的操作以維持 O(1),操作時間不變,對于二叉樹,1 倍的規模增量同樣帶來 1 次操作增量(每增加 1 層,葉子節點數量增加 1 倍),但這次操作無法抵消,時間永遠隨規模增加而單調遞增,然而由于二叉樹在操作過程中天然保序,就意味著其不真需要額外預留 1 倍空間以支撐規模。

時間不可壓縮,但空間可壓縮,這是時空的本質不同,接受一個隨規模遞增得慢的時間,去壓縮空間,這是所有機器的實現方式。背后是一個選擇問題,我們是選擇在時間中等待,去壓縮空間,還是選擇線性擴展空間,只為不等待,還是那個 “矩” 的長寬權衡。

直白說,空間不可無限擴展,我們傾向于壓縮它,我們設計的機器也是,而時間總是流逝不可壓縮,我們傾向于高效利用它,我們設計的機器也是。物件越來越多時,我們傾向于將它們分類疊放以便查找而不是在更大的空間平攤以便一眼瞅,空間的擴張總有極限,而時間卻無限延展。空間是共享的,我們的一生時間卻是私人的。

但我們還是希望有套稍微大一點哪怕極簡的房子,在多數場景,它比緊湊的裝修和儲物分類更簡單,更令人舒適,這還不夠的話,就看看我們智人的歷史,看看我們作為自己是如何學會 “集約(字面意思)” 的,我們的所謂文明,就是這種方式,所以我們設計的機器也是這種方式,但在大多數時間,我們卻是用相反的方式:
在這里插入圖片描述

首先要地盤,其次不要太大,這就是選擇 hash 的理由。

浙江溫州皮鞋濕,下雨進水不會胖。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/81892.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/81892.shtml
英文地址,請注明出處:http://en.pswp.cn/web/81892.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

kafka學習筆記(三、消費者Consumer使用教程——使用實例及及核心流程源碼講解)

1.核心概念與架構 1.1.消費者與消費者組 Kafka消費者是訂閱主題(Topic)并拉取消息的客戶端實例,其核心邏輯通過KafkaConsumer類實現。消費者組(Consumer Group)是由多個邏輯關聯的消費者組成的集合。 核心規則 同一…

《java創世手記》---java基礎篇(下)

《Java 創世手記 - 基礎篇(下)》 第五章:契約與規范 —— 接口 (Interfaces) 與抽象類 (Abstract Classes) 造物主,在你日益繁榮的世界里,你發現僅僅依靠“繼承”來構建“物種體系”有時會遇到一些限制。比如&#x…

氣鎮閥是什么?

01、閥門介紹: 油封機械真空泵的壓縮室上開一小孔,并裝上調節閥,當打開閥并調節入氣量,轉子轉到某一位置,空氣就通過此孔摻入壓縮室以降低壓縮比,從而使大部分蒸汽不致凝結而和摻入的氣體一起被排除泵外起此…

計算機一次取數過程分析

計算機一次取數過程分析 1 取址過程 CPU由運算器和控制器組成,其中控制器中的程序計數器(PC)保存的是下一條指令的虛擬地址,經過內存管理單元(MMU),將虛擬地址轉換為物理地址,之后交給主存地址寄存器(MAR),從主存中取…

從equals思考對“正念”的認知

正念 很多人聊正念,每個人有自己的解說,我聽到最符合邏輯的一個說法:正念就是對抗慣性。 如果嘗試過打坐或者冥想,就有一個說法叫正觀,什么意義呢?就是說感受自己的呼吸,自己的心跳&#xff0c…

信息安全管理與評估2025山東卷

需要其他賽題解析的可聯系博主

【leetcode】02.07. 鏈表相交

鏈表相交 題目代碼1. 計算兩個鏈表的長度2. 雙指針 題目 02.07. 鏈表相交 給你兩個單鏈表的頭節點 headA 和 headB ,請你找出并返回兩個單鏈表相交的起始節點。如果兩個鏈表沒有交點,返回 null 。 圖示兩個鏈表在節點 c1 開始相交: 代碼 …

可視化與動畫:構建沉浸式Vue應用的進階實踐

在現代Web應用中&#xff0c;高性能可視化和流暢動畫已成為提升用戶體驗的核心要素。本節將深入探索Vue生態中的可視化與動畫技術&#xff0c;分享專業級解決方案與最佳實踐。 一、 Canvas高性能渲染體系 01、Konva.js流程圖引擎深度優化 <template><div class"…

?模型驅動的DeepInsight Copilot在螞蟻的技術實踐

本文整理自潘蘭天&#xff08;螞蟻數據智能團隊數據分析平臺技術專家)在DA數智大會2025上海站的演講實錄。 本文圍繞AI技術在數據分析領域的應用及DeepInsight Copilot產品展開。DeepInsight是一款螞蟻長期深耕數據分析領域的BI產品&#xff0c;本文首先介紹了DeepInsight Copi…

Express教程【003】:Express獲取查詢參數

文章目錄 3、獲取URL中攜帶的查詢參數3.1 參數形式&#xff1a;查詢字符串3.2 參數形式&#xff1a;動態參數3.3 參數形式&#xff1a;Json數據 3、獲取URL中攜帶的查詢參數 3.1 參數形式&#xff1a;查詢字符串 1??通過req.query對象&#xff0c;可以訪問到客戶端通過查詢…

在CentOS7上使用tree查看目錄樹

文章目錄 1. 利用yum安裝tree2. 利用rpm安裝tree2.1 下載tree的rpm包2.2 上傳到云主機2.3 安裝tree軟件 3. 使用tree查看目錄樹4. 實戰小結 1. 利用yum安裝tree 執行命令&#xff1a;yum -y install tree CentOS7停止更新&#xff0c;即使更新鏡像源&#xff0c;也無法正常安裝…

大規模JSON反序列化性能優化實戰:Jackson vs FastJSON深度對比與定制化改造

背景&#xff1a;500KB JSON處理的性能挑戰 在當今互聯網復雜業務場景中&#xff0c;處理500KB以上的JSON數據已成為常態。 常規反序列化方案在CPU占用&#xff08;超30%&#xff09;和內存峰值&#xff08;超原始數據3-5倍&#xff09;方面表現堪憂。 本文通過Jackson與Fas…

華為交換機S12708常用命令

以下是華為S12708交換機&#xff08;高端園區/數據中心核心交換機&#xff09;的常用運維命令&#xff0c;涵蓋基礎配置、狀態查看、故障排查等場景&#xff1a; 一、基礎配置命令 1. 系統管理 system-view # 進入系統視圖 sysname S12708-Core # 設置設備名稱 clock timez…

通過海康螢石API控制家里相機的云臺及抓圖

通過海康螢石API控制家里相機的云臺及抓圖 一、背景二、環境準備2.1 注冊開發者賬號2.2 安裝依賴庫2.3 創建`.`env`文件三、代碼片段解釋3.1 加載并使用環境變量3.2 發送HTTP請求的封裝函數3.3 獲取AccessToken3.4 分頁查詢設備列表3.5 抓拍圖片3.6 開始云臺控制3.7 控制云臺并…

XCUITest 是什么

XCUITest&#xff08;全稱 Xcode UI Test&#xff09;是蘋果官方提供的 iOS/macOS UI 自動化測試框架&#xff0c;集成在 Xcode 開發工具中&#xff0c;專門用于測試 Swift/Objective-C 開發的應用程序。 1. XCUITest 的核心特點 ? 官方支持&#xff1a;蘋果原生框架&#xf…

mapbox高階,PMTiles介紹,MBTiles、PMTiles對比,加載PMTiles文件

????? 主頁: gis分享者 ????? 感謝各位大佬 點贊?? 收藏? 留言?? 加關注?! ????? 收錄于專欄:mapbox 從入門到精通 文章目錄 一、??前言1.1 ??mapboxgl.Map 地圖對象1.2 ??mapboxgl.Map style屬性1.3 ??Fill面圖層樣式1.4 ??PMTiles介紹1.5…

5.0以上版本antv/g6使用心得

1. 畫布只重新渲染數據 graph.render graph.drawgraph,fitview()graph.fitCenter()setData塞入新的數據 const updateGraph (data) > {if (!graph) {console.warn("Graph is not initialized");return;}graph.clear();graph.setData(data);graph.render(); };…

4.5V~100V, 3.8A 峰值電流限, 非同步, 降壓轉換器,LA1823完美替換MP9487方案

一&#xff1a;綜述 LA1823 是一款易用的非同步&#xff0c;降壓轉換器。 該模塊集成了 500mΩ 低導通阻抗的高側 MOSFET。LA1823 使用 COT 控制技術。此種控制方式有利于快速動態響應,同時簡化了反饋環路的設計。LA1823 可以提供最大 2A 的持續負載電流。LA1823有150kHz/240kH…

如何定位并優化慢 SQL?

如何定位并優化慢 SQL? 一、慢 SQL 的定義與影響 1.1 什么是慢 SQL? 慢 SQL是指執行時間超過預期閾值的SQL語句,通常由以下特征: 執行時間超過慢查詢閾值(如MySQL默認10秒)消耗大量CPU/IO資源導致連接堆積或系統負載升高關鍵結論:慢SQL是數據庫性能瓶頸的主要誘因,可…

提升WSL中Ubuntu編譯速度的完整指南

在 WSL&#xff08;Windows Subsystem for Linux&#xff09;中使用 make 編譯項目時&#xff0c;如果發現編譯速度非常慢&#xff0c;通常是由以下幾個原因導致的。以下是一些常見的排查和優化方法&#xff1a; &#x1f50d; 一、常見原因及解決方案 ? 1. 文件系統性能問題…