亚欧色一区w666天堂,色情一区二区三区免费看,少妇特黄A片一区二区三区,亚洲人成网站999久久久综合,国产av熟女一区二区三区

  • 發布文章
  • 消息中心
點贊
收藏
評論
分享

三種內存分配的算法比較

2024-11-18 09:21:50
14
0

內存的管理,其實就是三個層面,一個是上層的應用層,這個基本上所有的程序員都可以接觸到,一個數組的分配是分配在棧上還是堆上,都可以由開發人員來清晰的控制;第二層面是在庫這個層面上,包括前面分析的golang的內存管理,涉及到的內存逃逸,可能你認為的棧上的內存其實是分配到了堆上。最后就是內核層面的內存管理了,它是直接和物理內存打交道的,所以真正的內存分配和釋放歸根到底還在這里。
什么叫核心,就是難,不好整。所以在OS的開發上,內存管理這一塊仍然是硬骨頭。電腦為什么有時候突然死機,有相當一部分就是內存管理出現了問題,該用的內存分配不出來,該回收的內存回收不了,或者說回收了但都是碎片。業界目前對內存的管理有三個庫比較有名氣也就是tcmalloc,jecmalloc和ptmalloc。
內存管理的細節比較不好控制,但整體卻好理解,基本就是做生意的,從上游批發,向下游零賣,實現利潤的最大化即可。而庫做為應用和系統的中間層,就更要做好這種關系,把內存的應用效率最大化。

一、Tcmalloc

tcmalloc是Google的一種內存管理庫,其把內存分為頁Page,然后實現了三級緩存即ThreadCache(線程級緩存),Central Cache(中央緩存:CentralFreeeList),PageHeap(頁緩存)(可以翻看前面的tcmalloc的源碼分析系列),然后又通過Span和PageMap來處理頁和其的相互映射,達到快速定位的目的。
tcmalloc在鎖上使用了自旋鎖,速度肯定比ptmalloc效率要高。它的主要優點是:小內存可以不用鎖,大內存直接分配,使用自旋鎖替代了互斥鎖,內存碎片得到了進一步的控制。
但是,在某些場景下,比如大內存分配頻繁,CPU占用率會暴增。

二、Jemalloc

jemalloc是facebook的一種內存管理庫,其一個重點的特點是對多核多線程比較友好。換句話說越是好的硬件,越是復雜的軟件,內存足夠大的情況下,它的優勢越明顯。說到這里,通過前面分析多核和多線程編程其實就明白了,它一定是多核和多線程間的競態做的好。回想前面的多核編程中提到的,縮小鎖的精度,增加鎖的數量等等。在jemalloc中肯定有所體現。
jemalloc把內存底層的管理分成多個arenas,每個arenas有多個chunk,一個arenas對應著一個線程,并最終將二者綁定。這不就是剛剛提到的減少了鎖的粒度和范圍。但是arenas數量有限,不可能每個線程獨占一個arenas,這就需要內部的鎖來控制arenas的內部的內存的分配回收的安全性。
chunk默認是4M,它同樣以頁(4K)為基礎的管理單位。它和tcmalloc一樣也有size class的概念,其實就是進一步細分內存顆粒度的一種方式。在chunk中默認前6個頁是記錄元數據的,后面是通過bin記錄的runs,空閑的run由紅黑樹來管理。如同tcmalloc,切分內存是在chunk的基礎上進行的,分把其它按run進行使用。
jemalloc同樣也把內存分成三類 small object ( 1 ~57344)、 large object (57345 ~4MB )、 huge object(其它),它同樣也有一層緩沖層tcache,用來提高內存的管理速度。

三、Ptmalloc

此庫是GLIBC的內存分配的標準庫。它是在Doug Lea的malloc的主分配區基礎上增加了動態的內存分配管理,減少了內存分配過程的激烈的鎖的競爭。ptmalloc通過環形鏈表來管理它們,但在多線程訪問同一個分配區時,仍然需要加鎖。在ptmalloc中一個進程只有一個主分配區并有幾個動態分配區,動態分配區只可增長不可減少。主分配區通過sbrk從heap區域分配內存而動態分配區通過mmap分配內存。
在多線程中,ptmalloc是按照分塊處理內存的,也就是說把內存劃分成幾類,再劃分成塊:
Fast bins:小于64字節的內存,可以理解為小內存塊的高速緩存,回收和分配時會優先從這種鏈表中進行處理。
Usorted bin:一個,unsorted bin最先處理所有回收塊,分配時也要先從此處查看有無合適塊,找到直接返回否則將放入small bins或是large bins中。
Small bins:存放固定大小的塊,共64個bin,小內存分配時從此處匹配。其塊從16字節以相關8或16字節遞增。
Large bins:管理大于等于512字節或1024字節的空閑塊,這些chunk使用雙向鏈表的形式按大小順序排序,分配內存時按最近匹配方式從large bins中分配chunk。
ptmalloc有以下缺點:
top chunk的機制使得內存必須從后向前釋放。
多線程多核是痛點,內存的開銷相當大。
多線程中內存的分配回收無法做到很好平衡,即A線程的內存在用完成后無法在庫內部向其它線程開放使用。
chunk中浪費8字節,且容易產生內存碎片。

四、總結

總體的看來,ptmalloc是一種取中間的態度,盡量多適應一些場景,但效率就有一些問題了。而tcmalloc改進了ptmalloc一些問題并對多核多線程提供了一些優化,但自身占用的內存有所增多并且在某些場景下CPU占用率會大漲。jemalloc主要是對多核和多線程支持的更好,但內存占用更多,而且在一些普通場景下反而表現不是很優秀。這在實際的一些測試中也得到了驗證,一用來說,tcmalloc和jemalloc在多核和多線程下優勢更明顯,特別是在線程穩定且數量較多情況下,jemalloc更有優勢。
談起內存管理管理,大家不要怕,也不要覺得多么遙遠。如果寫過內存池,就可以說寫過最簡單的內存管理器,只不過沒有實現具體的一些細節,比如重載new和delete等接口罷了。很多東西是知易行難,做簡單容易,做精難。而內存管理就是這么一個方向。要想寫好一個內存管理,首先要明白前人怎么做的,現在流行的算法有什么優缺點,適應性如何?想要做一個全場景適合的優秀的內存管理器,目前看來應該是不可能的。一般來說是適應主流的場景或者特定的某些重要場景。畢竟現在各種硬件,各種機器都各有千秋,不可能一套機制全部能達到最優。
這也是好事啊,沒有最優,那就總有前進的方向。

0條評論
作者已關閉評論
趙****生
5文章數
0粉絲數
趙****生
5 文章 | 0 粉絲

三種內存分配的算法比較

2024-11-18 09:21:50
14
0

內存的管理,其實就是三個層面,一個是上層的應用層,這個基本上所有的程序員都可以接觸到,一個數組的分配是分配在棧上還是堆上,都可以由開發人員來清晰的控制;第二層面是在庫這個層面上,包括前面分析的golang的內存管理,涉及到的內存逃逸,可能你認為的棧上的內存其實是分配到了堆上。最后就是內核層面的內存管理了,它是直接和物理內存打交道的,所以真正的內存分配和釋放歸根到底還在這里。
什么叫核心,就是難,不好整。所以在OS的開發上,內存管理這一塊仍然是硬骨頭。電腦為什么有時候突然死機,有相當一部分就是內存管理出現了問題,該用的內存分配不出來,該回收的內存回收不了,或者說回收了但都是碎片。業界目前對內存的管理有三個庫比較有名氣也就是tcmalloc,jecmalloc和ptmalloc。
內存管理的細節比較不好控制,但整體卻好理解,基本就是做生意的,從上游批發,向下游零賣,實現利潤的最大化即可。而庫做為應用和系統的中間層,就更要做好這種關系,把內存的應用效率最大化。

一、Tcmalloc

tcmalloc是Google的一種內存管理庫,其把內存分為頁Page,然后實現了三級緩存即ThreadCache(線程級緩存),Central Cache(中央緩存:CentralFreeeList),PageHeap(頁緩存)(可以翻看前面的tcmalloc的源碼分析系列),然后又通過Span和PageMap來處理頁和其的相互映射,達到快速定位的目的。
tcmalloc在鎖上使用了自旋鎖,速度肯定比ptmalloc效率要高。它的主要優點是:小內存可以不用鎖,大內存直接分配,使用自旋鎖替代了互斥鎖,內存碎片得到了進一步的控制。
但是,在某些場景下,比如大內存分配頻繁,CPU占用率會暴增。

二、Jemalloc

jemalloc是facebook的一種內存管理庫,其一個重點的特點是對多核多線程比較友好。換句話說越是好的硬件,越是復雜的軟件,內存足夠大的情況下,它的優勢越明顯。說到這里,通過前面分析多核和多線程編程其實就明白了,它一定是多核和多線程間的競態做的好。回想前面的多核編程中提到的,縮小鎖的精度,增加鎖的數量等等。在jemalloc中肯定有所體現。
jemalloc把內存底層的管理分成多個arenas,每個arenas有多個chunk,一個arenas對應著一個線程,并最終將二者綁定。這不就是剛剛提到的減少了鎖的粒度和范圍。但是arenas數量有限,不可能每個線程獨占一個arenas,這就需要內部的鎖來控制arenas的內部的內存的分配回收的安全性。
chunk默認是4M,它同樣以頁(4K)為基礎的管理單位。它和tcmalloc一樣也有size class的概念,其實就是進一步細分內存顆粒度的一種方式。在chunk中默認前6個頁是記錄元數據的,后面是通過bin記錄的runs,空閑的run由紅黑樹來管理。如同tcmalloc,切分內存是在chunk的基礎上進行的,分把其它按run進行使用。
jemalloc同樣也把內存分成三類 small object ( 1 ~57344)、 large object (57345 ~4MB )、 huge object(其它),它同樣也有一層緩沖層tcache,用來提高內存的管理速度。

三、Ptmalloc

此庫是GLIBC的內存分配的標準庫。它是在Doug Lea的malloc的主分配區基礎上增加了動態的內存分配管理,減少了內存分配過程的激烈的鎖的競爭。ptmalloc通過環形鏈表來管理它們,但在多線程訪問同一個分配區時,仍然需要加鎖。在ptmalloc中一個進程只有一個主分配區并有幾個動態分配區,動態分配區只可增長不可減少。主分配區通過sbrk從heap區域分配內存而動態分配區通過mmap分配內存。
在多線程中,ptmalloc是按照分塊處理內存的,也就是說把內存劃分成幾類,再劃分成塊:
Fast bins:小于64字節的內存,可以理解為小內存塊的高速緩存,回收和分配時會優先從這種鏈表中進行處理。
Usorted bin:一個,unsorted bin最先處理所有回收塊,分配時也要先從此處查看有無合適塊,找到直接返回否則將放入small bins或是large bins中。
Small bins:存放固定大小的塊,共64個bin,小內存分配時從此處匹配。其塊從16字節以相關8或16字節遞增。
Large bins:管理大于等于512字節或1024字節的空閑塊,這些chunk使用雙向鏈表的形式按大小順序排序,分配內存時按最近匹配方式從large bins中分配chunk。
ptmalloc有以下缺點:
top chunk的機制使得內存必須從后向前釋放。
多線程多核是痛點,內存的開銷相當大。
多線程中內存的分配回收無法做到很好平衡,即A線程的內存在用完成后無法在庫內部向其它線程開放使用。
chunk中浪費8字節,且容易產生內存碎片。

四、總結

總體的看來,ptmalloc是一種取中間的態度,盡量多適應一些場景,但效率就有一些問題了。而tcmalloc改進了ptmalloc一些問題并對多核多線程提供了一些優化,但自身占用的內存有所增多并且在某些場景下CPU占用率會大漲。jemalloc主要是對多核和多線程支持的更好,但內存占用更多,而且在一些普通場景下反而表現不是很優秀。這在實際的一些測試中也得到了驗證,一用來說,tcmalloc和jemalloc在多核和多線程下優勢更明顯,特別是在線程穩定且數量較多情況下,jemalloc更有優勢。
談起內存管理管理,大家不要怕,也不要覺得多么遙遠。如果寫過內存池,就可以說寫過最簡單的內存管理器,只不過沒有實現具體的一些細節,比如重載new和delete等接口罷了。很多東西是知易行難,做簡單容易,做精難。而內存管理就是這么一個方向。要想寫好一個內存管理,首先要明白前人怎么做的,現在流行的算法有什么優缺點,適應性如何?想要做一個全場景適合的優秀的內存管理器,目前看來應該是不可能的。一般來說是適應主流的場景或者特定的某些重要場景。畢竟現在各種硬件,各種機器都各有千秋,不可能一套機制全部能達到最優。
這也是好事啊,沒有最優,那就總有前進的方向。

文章來自個人專欄
文章 | 訂閱
0條評論
作者已關閉評論
作者已關閉評論
0
0