Nginx 資料結構之 Array、List、Queue
一、背景
之前在內部分享了一次 Nginx,並寫了一篇文章《 ofollow,noindex" target="_blank">一次 Nginx 分享 》。
後來分享了 Nginx 很魔幻的記憶體池文章《 Nginx 中的記憶體池 》。
魔幻不是由於實現的有多高階,而是實現的非常簡單,簡單到什麼都沒有,資料結構的功能都耦合到業務實現中去了。
今天,我們來看看 Nginx 的 Array、List、Queue資料結構吧,看了更魔幻。
二、Nginx 的 Array
Nginx 中 Array 只對外提供了四個函式:建立陣列、回收陣列、申請一個元素、申請n個元素。
建立陣列函式用於申請一個數組頭和長度為 n
大小為 size
的連續節點。
回收陣列函式用於回收記憶體。
申請一個元素會先判斷是否還有剩餘空間,就返回最後一個空閒的節點。
如果不夠了,先判斷當前陣列是不是在記憶體池最後分配的。如果是最後分配的,而且還有空閒空間,就直接擴大記憶體。
而記憶體池也滿了,那就重新按兩倍法申請一個新的記憶體,資料 memcpy
過去。
舊的記憶體也沒有回收。
三、Nginx的 List
Nginx 的 List 保持了傳統的魔幻風格,只有兩個函式: create
函式 和 push
函式。
建立函式和 Array
類似,申請 n
個元素。
push
函式和陣列的功能也類似,從前向後返回一個空節點。
而當空節點用完時,這裡會去申請一個大小為 n
的 List
,然後當做連結串列掛在最後面。
這個不就是我們之前在《 從零開始學演算法:6.連結串列 》文章裡介紹的分塊連結串列嗎?
還有其他功能嗎?沒有了
四、Nginx 的 Queue
前面看了 Nginx
的 Array
和 List
,竟然和我們之前認識的不一樣。
那佇列呢,和你認識的也不一樣的。
佇列只提供了兩個函式: queue_middle
和 queue_sort
。
對於其他的,都是巨集的形式提供,比如 insert_head
、 insert_after
、 insert_remove
等。
看到這裡,業內人士會發出驚呼:這哪是佇列呢?這明明是連結串列嘛!
是的,你們是正確的,在 Nginx
裡面看到的名字和具體實現差異很大的。
我們看到的名字是佇列,實際是連結串列。
看到的是連結串列,實際是分塊連結串列。
那提供的兩個函式是什麼功能呢?
顧名思義,第一個函式是查詢連結串列的中值,第二個函式是對連結串列排序。
1.中值查詢
下面我們來看看相關實現吧,很簡單。
連結串列查詢中值,使用了另一道經典連結串列面試題的思想。
面試題:怎麼判斷連結串列有環?
看到這個面試題,很多工作的人都可以說上答案來吧。
典型的做法是兩倍追趕法。
而對於連結串列,查詢中值也是使用兩倍追趕法來實現的。
2.連結串列排序
連結串列排序那就很樸素了,使用氣泡排序即可。
五、最後
Nginx
裡面資料結構都是半成品,一半在資料結構中實現了,一半在業務程式碼中呼叫資料結構時實現。
是的,耦合就是這麼深,這樣那些實現的資料節後我們就不能拿出來單獨使用了。
為啥這樣做就不得而知了。
今天分享一本記憶體相關的數,名字叫做《程式設計珠璣》,公眾號後臺回覆”程式設計珠璣”領取。
本文首發於公眾號:天空的程式碼世界,微信號:tiankonguse-code。