国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

Linux Glibc 內存站崗問題及解決方法

系統 Linux
對于嵌入式設備來說,用戶態內存管理是一項基礎功能,目前主流的用戶態內存管理庫有glibc、uclibc、tcmalloc、jemalloc等。

0引言

對于嵌入式設備來說,用戶態內存管理是一項基礎功能,目前主流的用戶態內存管理庫有glibc、uclibc、tcmalloc、jemalloc等。

本文基于glibc2.17版本進行分析,圍繞glibc內存分配原理、內存站崗問題形成原因展開討論,并對glibc緩存大量內存(高達幾十個 G甚至上百 G)且不釋放的問題給出一種解決方案。

筆者遇到的問題是基于glibc進行內存管理的64 位Linux系統。具體現象如下:設備32G物理內存,在大規格打流情況下,某用戶進程占用的物理內存暴漲至20G左右。

在停止打流后,觀察到業務模塊已經釋放了絕大部分內存,但是進程占用的物理內存依然達到16G左右,此后內存狀況一直維持該狀態,導致系統內存緊張,若疊加上其他業務則出現了OOM的現象,已排除該進程內存泄露的可能性。

1Glibc內存分配基本原理

Glibc使用了ptmalloc的內存管理方式,本文在描述時均使用glibc來稱呼。Glibc申請內存時是從分配區申請的,分為主分配區和非主分配區,分配區都有鎖,在分配內存前需要先獲取鎖,然后再去申請內存。

一般進程都是多線程的,當多個線程同時需要申請內存時,如果只有一個分配區,那么效率太低。

glibc為了支持多線程的內存申請釋放,會在多個線程同時需要申請內存時根據cpu核數分配一定數量的分配區,將分配區分配給線程。如果線程數量較多,則會出現多個線程爭用一個分配區的的情況,這里不展開。

內存申請基本原理:當用戶調用malloc申請內存時,glibc會查看是否已經緩存了內存,如果有緩存則會優先使用緩存內存,返回一塊符合用戶請求大小的內存塊。

如果沒有緩存或者緩存不足則會去向操作系統申請內存(可通過brk、mmap申請內存),然后切一塊內存給用戶,如圖1所示。

圖 1

內存釋放基本原理:當業務模塊使用完畢后調用free釋放內存時,glibc會檢查該內存塊虛擬地址上下內存塊的使用狀態(fast bin除外)。若其上一塊內存空閑,則與上一塊內存進行合并。若下一塊內存空閑,則與下一塊內存進行合并。如圖2所示。

若下一塊內存時top chunk(top chunk一直是空閑的),則看top chunk的大小是否超過一個閾值,如果超過一個閾值則將其釋放給OS,如圖3所示。

圖2

圖3

2Glibc內存站崗及其原因

內存站崗概念:

內存站崗指的是glibc從OS申請到內存后分配給業務模塊,業務模塊使用完畢后釋放了內存,但是glibc沒有將這些空閑內存釋放給OS,也就是緩存了很多空閑內存無法歸還給系統的現象。

內存站崗原因:

glibc設計時就確定其內存是用于短生命周期的,因此在設計上內存釋放給OS的時機是當top chunk的大小超過一個閾值時會釋放top chunk的一部分內存給OS。當top chunk不超過閾值就不會釋放內存給OS。

那么問題來了,若與top chunk相鄰的內存塊一直在使用中,那么top chunk就永遠也不會超過閾值,即便業務模塊釋放了大量內存,達到幾十個G 或者上百個G,glibc也是無法將內存還給OS的。

對于glibc來說,其有主分配和非主分配區的概念。主分配通過sbrk來增加分配區的內存大小,而非主分配區則是通過一個或多個mmap出來的內存塊用鏈表鏈接起來模擬主分配區的。為了更清晰的解釋內存站崗,下面舉個例子來說明主分配區的內存站崗,如圖4所示。

圖4

如上有(a) (c) (e) (g)內存塊正在使用,故而導致了空閑內存(b) (d) (f)無法和top chunk連成一塊更大的空閑內存塊,glibc的閾值(64位系統默認是128K),盡管目前空閑內存有將近130M,也無法還給OS。

接下來看非主分配區的內存站崗,如圖 5 所示,實際的非主分配區可能有很多個heap,這里假設只有4個heap。

圖5

在定位過程中,筆者與同事討論過多次如何解決站崗。在一次討論過程中由鄧竑杰提出降低heap的size(類似于tcmalloc的做法),雖然實測后發現完全沒有效果,但是為后續解決問題起到了啟示作用。

后面筆者在走讀代碼時發現這是glibc原生機制,同時筆者在查看內存布局時觀察到非主分配區大量heap均為free狀態。原有機制是先釋放heap3,如果heap3有內存在使用,盡管heap0、heap1、heap2的內存都釋放了,那也是無法釋放給系統。

glibc有多個分配區,每個分配區都幾百 M 空閑內存的話,則整個進程占用達到幾十個G也就不奇怪了。

3Glibc內存站崗解決方法及patch

在內存釋放時,對于主分配區和非主分配其走的流程是不一樣的,我們64位系統的進程內存模型為經典模式,棧是從高地址向低地址生長的。

對于主分配區的內存站崗我還沒有遇到過,若主分配區內存站崗,一種方法是可以嘗試madvise將主分配區的pagesize對齊的空閑內存進行釋放,但是這樣效果可能不太明顯。

另外一種是通過創建線程,然后將主線程的業務移到新線程即可,這樣主分配區就不會造成站崗了,而將站崗轉移到了非主配區,而非主分配區則是我們接下來要進行優化的主戰場。

針對非主分配區進行兩處優化:

a) heap0,heap1,heap2是空閑的,那么我們就可以將heap1,heap2釋放掉;

b) heap默認是64M,降低每個heap的size(筆者測試時設置為512K)。

圖 6

這里需要特別解釋一下為什么不釋放heap0和最后一個heap3,heap0的組成如圖7所示。圖左邊是第一個heap即heap0,圖右邊是最后一個heap即heap3。

從圖中可以清晰的看到如若釋放掉heap0那么會將struct malloc_state結構體釋放,會造成進程崩潰。右邊這個由于有在用的內存,也不能釋放掉。當然如果heap3的內存全部被釋放了,則由glibc原生代碼進行了處理,patch不再處理。

圖 7

經過修改glibc源碼,優化其釋放機制,實際打流測試。

在打流到峰值后,進程使用了20G的內存,在停止打流后數秒內便恢復到了打流前的內存水平,進程所占用的內存基本還給系統了。至此,glibc內存站崗問題得到解決。

以上我們介紹了如何解決內存站崗的原理,紙上得來終覺淺,現在我們看patch源碼實現。

目前筆者已經將該優化的patch提交到開源社區審核,提交到社區的patch未對heap的size進行修改,這是因為想要謹慎一些,畢竟開源的代碼使用場景較多,如有需要可自行決定heap的size。

Patch基于glibc2.17代碼

  1. 1. Index: arena.c 
  2. 2. =================================================================== 
  3. 3. --- arena.c (revision 2) 
  4. 4. +++ arena.c (working copy) 
  5. 5. @@ -652,7 +652,7 @@ 
  6. 6. 
  7. 7. static int 
  8. 8. internal_function 
  9. 9. -heap_trim(heap_info *heap, size_t pad) 
  10. 10. +heap_trim(heap_info *heap, heap_info* free_heap, size_t pad) 
  11. 11. { 
  12. 12. mstate ar_ptr = heap->ar_ptr; 
  13. 13. unsigned long pagesz = GLRO(dl_pagesize); 
  14. 14. @@ -659,7 +659,29 @@ 
  15. 15. mchunkptr top_chunk = top(ar_ptr), p, bck, fwd; 
  16. 16. heap_info *prev_heap; 
  17. 17. long new_size, top_size, extra, prev_size, misalign; 
  18. 18. + heap_info *last_heap; 
  19. 19. 
  20. 20. + /*Release heap if possible*/ 
  21. 21. + last_heap = heap_for_ptr(top_chunk); 
  22. 22. + if ((NULL != free_heap->prev) && (last_heap != free_heap)){ 
  23. 23. + p = chunk_at_offset(free_heap, sizeof(*free_heap)); 
  24. 24. + if (!inuse(p)){ 
  25. 25. + if (chunksize(p)+sizeof(*free_heap)+MINSIZE==free_heap->size){ 
  26. 26. + while (last_heap){ 
  27. 27. + if (last_heap->prev == free_heap){ 
  28. 28. + last_heap->prev == free_heap->prev; 
  29. 29. + break; 
  30. 30. + } 
  31. 31. + last_heap = last_heap->prev; 
  32. 32. + } 
  33. 33. + ar_ptr->system_mem -= free_heap->size
  34. 34. + arena_mem -= free_heap->size
  35. 35. + unlink(p, bck, fwd); 
  36. 36. + delete_heap(free_heap); 
  37. 37. + return 1; 
  38. 38. + } 
  39. 39. + } 
  40. 40. + } 
  41. 41. /* Can this heap go away completely? */ 
  42. 42. while(top_chunk == chunk_at_offset(heap, sizeof(*heap))) { 
  43. 43. prev_heap = heap->prev; 
  44. 44. Index: malloc.c 
  45. 45. =================================================================== 
  46. 46. --- malloc.c (revision 2) 
  47. 47. +++ malloc.c (working copy) 
  48. 48. @@ -915,7 +915,7 @@ 
  49. 49. # if __WORDSIZE == 32 
  50. 50. # define DEFAULT_MMAP_THRESHOLD_MAX (512 * 1024) 
  51. 51. # else 
  52. 52. - 
  53. # define DEFAULT_MMAP_THRESHOLD_MAX (4 * 1024 * 1024 * sizeof(long)) 
  54. 53. +# define DEFAULT_MMAP_THRESHOLD_MAX (256 * 1024) 
  55. 54. # endif 
  56. 55. #endif 
  57. 56. 
  58. 57. @@ -3984,7 +3984,7 @@ 
  59. 58. heap_info *heap = heap_for_ptr(top(av)); 
  60. 59. 
  61. 60. assert(heap->ar_ptr == av); 
  62. 61. - heap_trim(heap, mp_.top_pad); 
  63. 62. + heap_trim(heap, heap_for_ptr(p), mp_.top_pad); 
  64. 63. } 
  65. 64. } 

結束語

不同的內存管理方式均有其優勢和缺陷,由于工作需要,筆者有幸研究過glibc、tcmalloc、uclibc內存管理,本文討論了glibc內存管理存在的一個共性問題,并給出可行的解決方案。

對于內存站崗問題,一般的做法是用戶自己緩存一些長時間不釋放的內存。另一種是干脆將glibc替換為tcmalloc。因為 tcmalloc 的 span比較小,所以站崗發生的概率極低,即便發生也就站崗一個span的大小。若由于某些原因不能用tcmalloc代替glibc的場景,如上的解決思路可以嘗試一下,該問題也困擾我們多時了,花費了較長時間和較多精力去定位。

 

在glibc2.28的版本中,glibc有了tcache的特性,對于業務進程使用大量小內存的場景則更加容易出現內存站崗問題。在撰寫本文時查看了glibc2.33版本,開源社區還未對該問題進行修改(或許是開源社區大神認為這不是glibc的問題,而是用戶不釋放內存)。

 

責任編輯:武曉燕 來源: Linux閱碼場
相關推薦

2009-07-01 18:14:36

JSP亂碼

2010-08-12 09:30:08

Flex內存泄露

2022-04-02 20:27:30

ETS操作系統鴻蒙

2010-06-21 09:54:50

Linux Aplay

2011-05-06 17:25:58

硒鼓

2011-08-24 17:41:16

MySQL死鎖

2010-08-10 10:10:34

Flex內存泄露

2011-06-16 10:27:55

.NET內存泄漏

2017-06-14 22:11:57

數據庫MySQL死鎖

2009-08-24 10:37:11

Silverlight

2022-04-06 10:09:17

云服務云計算

2010-12-27 10:48:10

VirtualboxFreedos

2021-01-12 11:40:12

SonarQube平臺數據項目授權

2025-04-07 07:20:35

SQL慢查詢性能

2018-11-01 15:26:38

開源軟件安全

2019-10-11 19:45:28

SparkSQLHiveHadoop

2009-03-04 10:38:36

Troubleshoo桌面虛擬化Xendesktop

2010-08-31 13:49:12

CSS

2016-11-14 10:06:04

大數據max位圖

2011-04-29 12:54:09

IBM內存
點贊
收藏

51CTO技術棧公眾號

欧美一区91| 欧美一区二区视频在线观看2022| 亚洲韩国在线| 欧美激情偷拍自拍| 韩国三级电影久久久久久| 精精国产xxxx视频在线野外| 色婷婷狠狠综合| 在线播放三级网站| 亚洲尤物视频在线| 国产毛片视频| 亚洲精品欧美在线| 97影院理论午夜| 中文字幕永久在线不卡| 美女mm1313爽爽久久久蜜臀| 成人久久精品视频| 久操国产精品| 5278欧美一区二区三区| 91成人噜噜噜在线播放| 欧美激情国产精品| 岛国精品一区| 欧美亚洲视频一区二区| 美女呻吟一区| 日韩在线观看免费全| 成人看片网站| 久久蜜桃精品| 5月丁香婷婷综合| 国产精品欧美日韩| 日本夜爽爽一二区| 久久66热偷产精品| 91视频一区二区三区| 熟女少妇在线视频播放| 国产精品一级在线| 欧美唯美清纯偷拍| 国产一区二区三区不卡在线| 精品精品99| 精品久久久一区二区| 久久国产精品电影| 亚洲aⅴ男人的天堂在线观看| 快射视频在线观看| 国模大尺度一区二区三区| 67194成人在线观看| 在线观看三级网站| 色婷婷综合网站| 久久香蕉av| 国产日韩精品久久| 亚洲第一区视频| 天堂久久一区二区三区| 伊人久久五月天| 亚洲成人免费视频| 日韩你懂的电影在线观看| 国内精品一区二区三区| 你懂的免费在线观看视频网站| 在线播放一区二区精品视频| bt7086福利一区国产| 成人免费在线看片| 伊人春色在线| 视频一区中文字幕| 人妻夜夜添夜夜无码av| 国产精品久久看| 日韩伦理在线电影| 蜜臀精品一区二区三区在线观看| 国产三级中文字幕| 亚洲精品亚洲人成人网在线播放| 黄色网址在线免费| 欧美激情国产精品| 免费精品视频| 成人综合网址| 欧美成人a在线| 日韩最新在线| 亚洲高清123| 亚洲一二三区在线观看| 人人超在线公开视频| 国产69精品久久久久99| 久久久久久久波多野高潮日日| 天天干天天操天天玩| 亚洲第一福利网站| 日本一区二区免费高清| a天堂资源在线观看| 在线视频你懂得一区| 麻豆久久一区| 亚洲精品视频一区二区三区| 亚洲成人自拍网| 欧美日韩伦理一区二区| 精品中文字幕人| 亚洲永久免费av| 亚洲国产一区二区久久| 青青草久久网络| 激情av一区二区| 日韩深夜福利网站| 国产精品一区二区久久精品爱涩| 中文字幕区一区二区三| 精品动漫一区二区| 亚洲国产专区校园欧美| 国产在线视频91| 欧美久久高跟鞋激| 无码专区aaaaaa免费视频| 亚洲三级网站| 欧洲精品在线播放| 丝袜亚洲欧美日韩综合| 色噜噜偷拍精品综合在线| 精品理论电影| 啦啦啦在线视频免费观看高清中文| 欧美日韩在线精品| 色综合久久综合网97色综合| 在线观看的日韩av| 日韩在线电影| 青青久在线视频| 欧美大片免费播放| 欧美一区二区三区艳史| 欧美三级资源在线| 成人三级视频| 中文在线有码| 欧洲熟妇精品视频| 国产精品美女久久久久av福利| 国产精品福利av| 蜜桃国内精品久久久久软件9| 超碰国产在线观看| 久久精品日韩精品| 欧美成人剧情片在线观看| 中文字幕一区二区在线观看| 欧美欧美天天天天操| 欧美激情777| 成人免费看视频网站| 福利在线视频导航| 久久人妻精品白浆国产 | 亚洲经典在线| 国产一级视频| 日本精品性网站在线观看| 国产欧美精品区一区二区三区| 成人综合日日夜夜| 黄色免费观看视频网站| 日韩精品中文字幕在线| 波多野结衣与黑人| 精品国产乱码久久| 日韩有码一区二区三区| 18av在线播放| 欧美一区免费视频| 亚洲精品一区二区三区福利| 免费欧美在线视频| 亚洲欧美一区二区三区| 久青草视频在线播放| 久久视频在线视频| 欧美激情中文不卡| 红桃成人av在线播放| 亚洲52av| 免费av在线一区二区| 亚洲国内精品视频| 成人网在线播放| 国产精品115| 特黄特黄的视频| 91欧美视频网站| 欧美成人一区二区| av资源网一区| 西野翔中文久久精品字幕| 绯色av一区| 欧美一区二区三区四区在线观看地址| 欧美va亚洲va| ww亚洲ww在线观看国产| 神马久久一区二区三区| 在线观看麻豆蜜桃| 九九久久九九久久| 欧美黑人巨大xxx极品| 亚洲va欧美va人人爽午夜| 99精品视频免费| 国产精品毛片久久久久久久久久99999999| 久久久久久久久久久福利| 国产精品www网站| 日韩欧美国产1| 国产欧美一区二区三区鸳鸯浴| 精品一区不卡| а√天堂8资源中文在线| 黄色av免费在线播放| 91亚洲国产精品| 日韩精品欧美激情| 亚洲色图.com| 水蜜桃久久夜色精品一区的特点| 性欧美video另类hd尤物| 在线播放av更多| 福利视频免费在线观看| 91久久精品国产| 在线电影av不卡网址| 一级日本不卡的影视| 韩日av一区二区| 99久久99久久精品国产片果冰| 日韩精品美女| 一二三四社区在线视频6| 中国一级大黄大黄大色毛片| 国产成人精品免费视频| 亚洲精品美女久久| 亚洲成人你懂的| 不卡av电影在线播放| 好看的日韩av电影| 9l视频自拍九色9l视频成人| 在线观看的网站你懂的| 成年人黄色电影| 欧美图片激情小说| 久久av一区二区三区漫画| 97在线视频免费观看| 亚洲欧美日韩国产中文| 欧美亚洲丝袜传媒另类|