0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Linux內(nèi)核內(nèi)存回收對嵌入式系統(tǒng)的重要性

Linux閱碼場 ? 來源:Linux閱碼場 ? 作者:小輝 ? 2022-07-14 09:25 ? 次閱讀

前傳

嵌入式系統(tǒng)的內(nèi)存回收還是比較重要的,因為這塊涉及到程序運行性能。

嵌入式系統(tǒng)(比如平板,手機)會更加關(guān)注單機性能優(yōu)化,因而會更加重視系統(tǒng)內(nèi)存回收。

嵌入式系統(tǒng)不像互聯(lián)網(wǎng)那種大型分布式服務(wù)器系統(tǒng),他們往往內(nèi)存和存儲容量比較充裕,因而關(guān)注點在分布式方面,對單機性能不夠重視。嵌入式系統(tǒng),在有限的內(nèi)存和存儲空間因素制約下,會更加關(guān)注單機性能優(yōu)化。

而內(nèi)存回收這塊是比較重要的,因為內(nèi)存回收做的不好,內(nèi)存壓力得不到釋放,最直接的是內(nèi)存壓力會轉(zhuǎn)化為IO壓力,對系統(tǒng)io性能造成影響。另外也會轉(zhuǎn)換為cpu壓力,影響程序的cpu資源使用。

所以結(jié)合我對內(nèi)存回收方面的調(diào)研,想重點寫下對Linux內(nèi)核內(nèi)存回收這塊代碼的理解,也想分享下我在這塊的調(diào)研心得。

內(nèi)存回收的重要性

這個內(nèi)存回收方面的優(yōu)化對系統(tǒng)到底有怎樣的影響,我想舉幾個例子會詳細(xì)透徹地講下內(nèi)存回收方面的優(yōu)化,還有給系統(tǒng)帶來的好處。

一 、內(nèi)存回收在高負(fù)載系統(tǒng)性能方面的優(yōu)化

1 問題現(xiàn)象:

移動設(shè)備上(比如平板,手機)后臺u盤傳輸大批量數(shù)據(jù)時,前臺桌面操作卡頓。

2 原因分析:

1: u盤拷貝數(shù)據(jù)量大時,會導(dǎo)致系統(tǒng)內(nèi)存里面臟頁變多,然后可用內(nèi)存變少。

2: 然后前臺平板操作時,會allocate_pages去分配內(nèi)存頁。這個時候會陷入slow path,去觸發(fā)內(nèi)存回收。

由于此時有大量臟頁存在,內(nèi)存回收會比較耗時,這樣前臺操作的內(nèi)存分配性能也會變差。同時回收臟頁時產(chǎn)生的io壓力對前臺操作時的io性能也會有影響。

因為前臺的內(nèi)存和io性能都受到了影響,所以前臺平板操作才會變卡頓。

3 一點性能優(yōu)化心得方面的精彩點評:

這是一個典型的單機系統(tǒng)里面比較特色的內(nèi)存和io相互作用導(dǎo)致的性能問題。

1) 內(nèi)存回收時,不得不做很多臟頁回寫工作

因為單機系統(tǒng)比如平板,手機,里面大都是buffer寫,寫到page cache里面就認(rèn)為工作完成就成功返回了, 雖然省事,但是寫到page cache里面必然會帶來額外的內(nèi)存消耗。

所以我們看到嵌入式系統(tǒng)里面很多場景下(比如上面的u盤拷貝場景),會造成某些時間段內(nèi)系統(tǒng)page cache占內(nèi)存多,其實是里面積累很多臟頁。

pagecache占內(nèi)存多,系統(tǒng)free內(nèi)存就會變少。而偏偏系統(tǒng)的write back線程又不活躍(手機ext4文件系統(tǒng)里面開啟延遲寫后,系統(tǒng)每隔30s才回寫一次臟頁),這樣就會造成 [內(nèi)存分配 → 不得不做內(nèi)存回收] 這樣路徑下,才會解決pagecache占內(nèi)存多問題,具體就是觸發(fā)做臟頁回寫工作。

2) 問題就在于:

系統(tǒng)的io寫性能不好時,會影響到page cache里面的臟頁釋放。臟頁一旦得不到有效釋放,系統(tǒng)free內(nèi)存越來越少,這樣內(nèi)存分配性能也會受到影響。

同時內(nèi)存分配有問題或者回收效率不高,在處理臟頁回寫方面有缺陷時,也會產(chǎn)生額外的io壓力。所以是內(nèi)存和io相互影響,相互作用。

所以就有了內(nèi)核社區(qū)每年那個storage and mm國際會議,單機系統(tǒng)里面出現(xiàn)性能問題時,內(nèi)存和io往往需要同時去優(yōu)化。

3) 先去優(yōu)化內(nèi)存,如果不行,再去優(yōu)化io

系統(tǒng)的內(nèi)存和io相互作用導(dǎo)致的性能問題出現(xiàn)時,最好用這種優(yōu)化思路,原因很簡單,內(nèi)存優(yōu)化成本低,風(fēng)險小。

為什么國內(nèi)有很多技術(shù)文章或者書籍都詳細(xì)重點講linux內(nèi)核內(nèi)存管理,為什么文件系統(tǒng)和io這塊不去詳細(xì)講講,其中有一個重要的原因是:

因為國內(nèi)企業(yè)普遍看到了內(nèi)存優(yōu)化成本低,不行就多殺一些進(jìn)程或者優(yōu)化下內(nèi)存分配和回收,即使是內(nèi)存出問題,頂多重啟一下系統(tǒng),問題就沒了。

但是io這塊本身技術(shù)方面就比較復(fù)雜,光內(nèi)核里面,從vfs到ext4具體文件系統(tǒng),再到塊設(shè)備層,再到存儲bsp層,再到存儲硬件芯片層,這些每個層優(yōu)化的不好,都會出io性能問題,而且部署io性能優(yōu)化方案,往往又要對這些每個層都要有所熟悉,這樣才能保證優(yōu)化副作用降到最小。

這還是討論優(yōu)化技術(shù)本身的,還沒談到,如果存儲io出問題,手機上重要文件損壞,輕則用戶發(fā)現(xiàn)文件丟失(這樣的損壞和丟失是你再開機多少次都無法挽回的),重則無法開機事故就出來了。

詳細(xì)可以見我的另外一篇技術(shù)文檔:《手機Android存儲性能優(yōu)化架構(gòu)分析》。

4 解決思路:

在社區(qū)高版本內(nèi)核上面找了一些patch,這些patch是對內(nèi)核內(nèi)存回收方面的優(yōu)化,重點也是優(yōu)化臟頁過多時,內(nèi)存回收耗時問題的。

優(yōu)化1:

1)優(yōu)化原理

內(nèi)存回收時,提前喚醒write-back內(nèi)核線程,提前把所有的臟頁都寫入到磁盤上。這樣交給專門的內(nèi)核回寫線程來做臟頁回寫工作,這樣效率更高。

因為內(nèi)存回收路徑中做的臟頁回收是離散寫,具體是調(diào)用pageout → 文件系統(tǒng)writepage函數(shù),這樣每回只寫一個page,在lru鏈表上積累的臟頁比較多時,這樣回寫效率并不高,因此也影響了內(nèi)存回收。

提前喚醒writeback線程后,writeback線程寫會集中寫,具體是以inode為單元,會把每個inode上的臟頁數(shù)據(jù)通過ext4的writepages函數(shù),寫到磁盤上。

如果寫的臟頁數(shù)據(jù)量都一樣,集中寫會做io請求合并,減少io請求處理耗時,這樣顯然比內(nèi)存回收自己離散寫臟頁性能要好多了。

具體性能優(yōu)化數(shù)據(jù)可見我的另外一篇文檔:那些年解的疑難性能問題 - ext4碎片整理。

2)patch內(nèi)容

具體是社區(qū)這個patch: mm/vmscan: wake up flushers for legacy cgroups too.

在內(nèi)存回收必經(jīng)路徑shrink_inactive_list函數(shù)里面,判斷stat.nr_unqueued_dirty == nr_taken的話,說明此時內(nèi)核的inactive lru list里面積累了大量臟頁,需要喚醒writeback線程去集中大批量地寫一次。

優(yōu)化2:

1) 優(yōu)化原理

在內(nèi)存回收路徑里面盡量少回收臟頁,少觸發(fā)io操作,這樣會降低內(nèi)存回收direct reclaim路徑的耗時,也會間接優(yōu)化內(nèi)存分配slow_path的耗時。

同時為了保證多回收內(nèi)存,增加更多free page, 會多回收些干凈頁。核心工作是:

把active list上更多的page(比如clean page)加入到inactive list里面,這樣雖然會造成比如這些active clean page被回收后,很有可能還要被重新讀入內(nèi)存。但是這個負(fù)作用比起 陷入緩慢的write back臟頁操作不能立刻滿足前臺內(nèi)存分配需求 要輕得多。

因為存儲芯片讀是比寫要快很多的,所以上面雖然有那個負(fù)作用,但是不足為慮。

2) patch內(nèi)容

具體是社區(qū)這2個patch:

mm: vmscan: only write dirty pages that the scanner has seen twice.

在shrink_inactive_list函數(shù)里面,如果direct reclaim,則做以下工作:

是待回收頁是臟頁時,進(jìn)一步判斷如果該頁沒有設(shè)置reclaim標(biāo)記,那么就僅僅設(shè)置下relcaim標(biāo)記,重新放回active list上,而不去回收它。然后等到第2次再碰到該頁時,如果還是臟頁,再去回收它。

mm: vmscan: move dirty pages out of the way until they're flushed

在lru_add_drain里面的pagevec_move_tail_fn函數(shù)里面修改,搞成不管該page是否active,都盡可能地把它放到inactive list上去。

這樣會盡量把active list上的page往inactive list上轉(zhuǎn)移,因為上面patch是在inactive list上碰到臟頁放到active list上的,所以再帶上這個patch,那么最終效果是更多的clean page被搬到了inactive list上去,這樣就會有更多的page被回收掉。

這樣就會充分釋放了內(nèi)存,接下來的內(nèi)存分配性能就會得到優(yōu)化。

二、 內(nèi)存回收里面的boost watermark優(yōu)化改造

改造1

1 問題現(xiàn)象

嵌入式設(shè)備里面有時候會出現(xiàn)app熱啟動慢,抓trace分析后,是啟動時的io讀性能差,差的原因是很多讀不是從pagecache中讀,而是直接從磁盤上讀。

2 原因分析

有些嵌入式設(shè)備內(nèi)存并不充裕,然后從log中看到,出問題的內(nèi)核里面都開啟了boost watermark。這個特性一旦被開啟,就會使得內(nèi)核內(nèi)存回收變得更加活躍,并且是只回收干凈文件頁的,臟頁和匿名頁都不回收。

這個特性推出的目的本來是為了降低系統(tǒng)內(nèi)存碎片的(詳見我另外一篇文檔:android內(nèi)存碎片優(yōu)化梳理),但是結(jié)果在低內(nèi)存設(shè)備上副作用更加明顯,更加大于它的收益,把app啟動時io讀成功的文件頁都給回收了,這樣就會造成系統(tǒng)的整體io讀性能變差。

3 優(yōu)化思路

低內(nèi)存嵌入式設(shè)備上因為io讀性能差問題嚴(yán)重,所以可以關(guān)閉該boost watermark優(yōu)化,高內(nèi)存設(shè)備上保留。

ps:

性能優(yōu)化有時就是這樣一種折衷,優(yōu)化有時候會難免有一些副作用,怎么針對具體問題場景,做到衡量評估好收益和副作用的平衡和折衷,是關(guān)鍵的。

改造2

1 問題現(xiàn)象

移動設(shè)備上(比如手機,平板)相機場景里整機內(nèi)存壓力大,會造成相機相關(guān)進(jìn)程內(nèi)存分配性能差,出現(xiàn)相機操作卡頓問題。

2 原因分析

相機某些操作場景下,相機自身進(jìn)程會不可避免有高峰值內(nèi)存分配的需求。當(dāng)陡然切換到這些操作場景時,由于系統(tǒng)沒有做好應(yīng)對準(zhǔn)備,滿足不了相機內(nèi)存分配需求,就會造成相機內(nèi)存性能變差。

3 優(yōu)化思路

相機場景下可以部署下主動內(nèi)存回收方案,在高峰值內(nèi)存場景下,可以緩解相機內(nèi)存分配壓力。

主動內(nèi)存回收必須快捷高效,能短時間內(nèi)釋放出大量可用內(nèi)存出來。這樣可以借鑒下boost watermark的思想,先回收下文件頁,因為文件頁比匿名頁回收要省時多了。

另外一點是相機自身進(jìn)程的io讀需求比較少,io讀壓力不大,壓力大的是內(nèi)存和cpu,所以為了短時間內(nèi)釋放內(nèi)存壓力,是可以多回收些文件頁的。

同時改造下boost watermark,把它綁到小核上去干活,避免和相機進(jìn)程爭用cpu。

三、 從系統(tǒng)全局考慮部署高效內(nèi)存回收方案

1 問題背景

嵌入式系統(tǒng),諸如手機,平板,前面提過,內(nèi)存和存儲容量受限,但用戶對它的使用需求卻在日益膨脹,幾乎當(dāng)成電腦一樣在用。

所以單機系統(tǒng)里面,整機內(nèi)存壓力是比較大的,而內(nèi)存方面的優(yōu)化涉及面廣,拿android系統(tǒng)來說,從app到fwk, 再到native層的glibc庫,再到底層內(nèi)核,都會有內(nèi)存優(yōu)化空間。

內(nèi)核內(nèi)存優(yōu)化比較麻煩耗時些,而且有些內(nèi)存性能問題,從上層入手優(yōu)化,反而更加高效快捷些,所以需要從系統(tǒng)全局考慮出發(fā),去優(yōu)化整機內(nèi)存。

2 原生android已有的內(nèi)存回收方案

1)用戶態(tài)的lmkd + 內(nèi)核的內(nèi)存psi兩者結(jié)合,高效殺進(jìn)程

殺進(jìn)程是釋放整機內(nèi)存壓力最好的方式,系統(tǒng)整機free內(nèi)存很少時,通過殺掉一些手機后臺低優(yōu)先級進(jìn)程,可以快速地騰出可用內(nèi)存,供前臺app使用。

另外基于內(nèi)存psi感知,這樣可以更靈敏地感知到程序有性能問題時,就去及時殺進(jìn)程。

2)Lmkd殺進(jìn)程缺陷

目前的缺陷是,光根據(jù)adj來進(jìn)行殺進(jìn)程優(yōu)先級排序還不夠,有些用戶經(jīng)常使用到的app還是會被頻繁殺掉,這樣會影響到用戶體驗。

另外不區(qū)分主進(jìn)程和子進(jìn)程,殺掉主進(jìn)程就會影響到后臺app駐留。

所以還需要在fwk層做些優(yōu)化工作,因為fwk層最能感知到app業(yè)務(wù)層的變化,在這里最能根據(jù)用戶體驗來部署優(yōu)化方案。

3)其他的一些優(yōu)化方法

從性能優(yōu)化工作角度出發(fā),感覺到目前的linux內(nèi)核內(nèi)存管理這塊,更傾向于服務(wù)互聯(lián)網(wǎng)業(yè)務(wù)場景。嵌入式單機設(shè)備場景比如android手機,想往內(nèi)核主線分支進(jìn)性能優(yōu)化changes,會發(fā)現(xiàn)比較困難。

所以現(xiàn)在我們看到的比較新的版本上內(nèi)核內(nèi)存回收這塊還是有很多性能問題,有很多待優(yōu)化空間的。

所以一些諸如高通芯片原廠,在linux內(nèi)核主線版本上,會打上一些關(guān)于嵌入式系統(tǒng)方面的優(yōu)化(比如process reclaim等),才會交給我們使用。

Linux內(nèi)核內(nèi)存回收的一些問題和待優(yōu)化空間

一、 內(nèi)存回收目標(biāo)和收益方面的不確定性

1 內(nèi)存回收目標(biāo)

問題1)

direct reclaim時,nr_to_reclaim是它的回收目標(biāo),但這個現(xiàn)在固定死了是32個page(詳見__alloc_pages_direct_reclaim → try_to_free_pages里面的 nr_to_reclaim被強制賦值為SWAP_CLUSTER_MAX),

那么如果內(nèi)存分配只需要1 - 4個page時,陷入到slow path里面做內(nèi)存回收,客戶只需要回收1 - 4個page就行了,但是內(nèi)存回收這塊會多回收出額外的31個page出來。額外的回收工作必然會導(dǎo)致回收要多耗時點。

打開底層ftrace,會經(jīng)常看到前臺操作app時,對應(yīng)的缺頁異常里面會每次只分配1到4個page,說明在android系統(tǒng)里面分配少量page的需求還是很多的。

原因

這個地方定成32,可能是考慮到系統(tǒng)中有很多進(jìn)程在做并發(fā)direct reclaim的,所以為了權(quán)衡系統(tǒng)整體reclaim的壓力和避免更多有用內(nèi)存頁被回收掉,這個地方就定成了32.

問題2)

內(nèi)核內(nèi)存回收direct reclaim的必經(jīng)函數(shù)shrink_node_memcg最下面,完成回收目標(biāo)后,還要做rebalance the anon lru active/inactive ratio工作,勢必會增加direct reclaim進(jìn)程的耗時。

另外shrink_inactive_list里面還要做too_many_isolated工作,這個會導(dǎo)致direct reclaim進(jìn)程睡眠。

原因

可能是為了服務(wù)器場景考慮的,為了優(yōu)化系統(tǒng)全局內(nèi)存狀態(tài),做一些balance工作。但是嵌入式場景下,該內(nèi)存回收架構(gòu)并未區(qū)分前臺后,這樣前后臺進(jìn)程在direct reclaim方面一視同仁,

都要做很多balance系統(tǒng)的工作,這樣的話,會導(dǎo)致前臺app的內(nèi)存分配耗時增加。

總結(jié):

上面一些問題的發(fā)現(xiàn),說明內(nèi)存回收這塊目前的架構(gòu)設(shè)計是為服務(wù)器場景考慮的,而嵌入式場景,比如手機,比較關(guān)注前臺app進(jìn)程的響應(yīng)性能的情況下(詳見我的文檔:手機前后臺io分組優(yōu)化調(diào)研),

上面內(nèi)存回收的一些耗時不確定性問題,至少說明在內(nèi)存回收這個地方,嵌入式設(shè)備尤其是相機場景大內(nèi)存分配的情況下,還是會有優(yōu)化空間的。

2 內(nèi)存回收收益計算

問題

內(nèi)核在做內(nèi)存回收過程中,要調(diào)用shrink_slab去回收系統(tǒng)的一些緩存。但是內(nèi)核drivers/staging目錄下面一些緩存,比如ion緩存,就沒有計算這部分緩存實際被回收的page數(shù)量。

這樣會造成direct reclaim中,比如回收目標(biāo)是32個page,本來帶上ion cached部分,就達(dá)到回收目標(biāo)了,不需要再進(jìn)行新的一輪回收工作了。

但是由于漏統(tǒng)計了ion cached的回收部分,還得再多做一輪回收工作,直到回收夠32個page再結(jié)束。

原因

shrink_slab時,實際回收成功的文件系統(tǒng)緩存都可以被內(nèi)核內(nèi)存回收模塊統(tǒng)計到,但是ion cached這塊,可能是位于staging分支的緣故,內(nèi)核主線代碼對它的管理不是很到位而造成的。

二、 rmap查找的耗時

這個是目前內(nèi)核內(nèi)存回收中一個比較頭疼的性能問題。

1 問題現(xiàn)象

在android系統(tǒng)里面,用perf工具抓下kswapd的性能profile, 會發(fā)現(xiàn)內(nèi)核內(nèi)存回收這塊有很多工作花在了 page_referenced -> page_vma_mapped_walk這個地方了。

之前XXX的系統(tǒng)高負(fù)載時匿名頁回收性能調(diào)查博客里面,也提到了相機app進(jìn)程會卡在shrink_page_list → page_referenced函數(shù)里面時間還比較長。

2 原因分析

1)內(nèi)核內(nèi)存回收搞了個二次機會法,增加了rmap反查耗時。

二次機會法意味著所有的內(nèi)存頁在進(jìn)入inactive list后,幾乎都要做一遍page_check_references工作,這樣才能被真正回收掉。

這個地方的工作確實有必要,因為lru list只是保證了用戶進(jìn)程先分配使用的內(nèi)存頁放到tail,后分配使用的內(nèi)存頁放到了head.

但是在系統(tǒng)運行過程中,如果放到了inactive list tail的內(nèi)存頁被進(jìn)程再次訪問到,那么就會重新變回active,那么就得靠二次機會法來把它移到active list里面。

二次機會法靠這個page_check_references工作,來保證內(nèi)核內(nèi)存回收的都是最近不經(jīng)常被使用到的page.

2) android系統(tǒng)的共享頁很多,也增加了rmap反查耗時。

android里面的app進(jìn)程都是從zygote進(jìn)程fork出來的,并且app進(jìn)程自身也會fork出很多線程。這樣造成了android里面共享頁的確很多,同一個page被共享進(jìn)程的數(shù)目也很多。

這樣就會帶來page_referenced的反查耗時工作。

3) lru active list上也加了page_referenced的反查工作。

這部分反查工作一方面是為了recent_rotated計數(shù),最后是為了get_scan_count里面的確定file list和anon list的查找傾斜度。

高內(nèi)存壓力場合,get_scan_count里面也推薦用SCAN_EQUAL,而不是SCAN_FRACT,所以這種場合還是否有必要做上面傾斜度確定工作,需要再看看是否能進(jìn)一步優(yōu)化下。

另外一方面主要是為了在active page被降級加入到inactive lru list之前,做下清除映射該page的各用戶態(tài)進(jìn)程pte的referenced標(biāo)記工作。

因為要加入到inactive list上,至少說明此時該page已經(jīng)是stale page, 已經(jīng)被降級下來準(zhǔn)備要被回收了,所以應(yīng)該清除下映射該page的pte里面的referenced標(biāo)記了。

內(nèi)核內(nèi)存回收方面的一些梳理:

其實從這些內(nèi)存回收設(shè)計方面可以看出,linux內(nèi)存回收這塊還是基于一些經(jīng)驗主義的判斷,不可能做到特別準(zhǔn)確地識別出最久不被使用的內(nèi)存頁。

就是靠不斷地做rmap反查和一些經(jīng)驗主義判斷(文件頁先放到inactive list上,匿名頁先放到active list,內(nèi)核認(rèn)為匿名頁都是比文件頁更活躍的)

來最大程度上保證hot page(即每個進(jìn)程的working-set內(nèi)存頁)放到active list上,cold page(進(jìn)程的非woking set內(nèi)存頁)放到inactive list上去。

其中在每個page被回收之前,匿名頁一般被反查2次,文件頁一般被反查3次,反查的確比較耗時。

不過linux kernel在性能方面是針對通用系統(tǒng),重點是為服務(wù)器系統(tǒng)設(shè)計的,所以嵌入式方面還是有不少特殊場景(比如相機高內(nèi)存峰值出現(xiàn)場景)可以做內(nèi)核內(nèi)存回收方面的性能優(yōu)化的。

3 優(yōu)化方法

或者用app compact回收單進(jìn)程,或者借鑒下lwn上的這篇優(yōu)化文章:The multi-generational LRU,講的rmap反查的弊端和優(yōu)化方法。

或者我現(xiàn)在正在調(diào)研的思路:相機場景下,高效內(nèi)存回收思路。

如果要回收的內(nèi)存數(shù)量多,比如回收1 - 2G,那么其實可以識別出相機自身相關(guān)進(jìn)程使用的內(nèi)存page后,對非相機使用的page可以減少上面rmap的反查工作, 理由如下:

1) 因為非相機進(jìn)程即使發(fā)生page refault,也是僅僅影響的是非相機進(jìn)程的性能。

2) 在主動內(nèi)存回收之前,內(nèi)核的全局lru鏈表中已經(jīng)大概率是一個比較成熟,比較完美地冷熱內(nèi)存頁分離的狀況了(hot page放在active list,cold page放在inactive list上),這樣充分利用內(nèi)核的lru list,先回收冷頁。

3) 最重要此時相機操作需要大量內(nèi)存,而系統(tǒng)處于內(nèi)存緊缺狀況,需要短時間內(nèi)回收出大量內(nèi)存出來。

而此時結(jié)合下面的調(diào)研,就算做上面耗時的rmap反查工作,也會很容易出現(xiàn)比如幾秒鐘前才被訪問過的頁面可能都不會被視作活躍,而被回收掉(因為此時回收過程中頁掃描會出現(xiàn)地異常頻繁,會加速頁面老化)。

那還不如不做rmap反查,直接回收算了。

三 、內(nèi)核匿名頁回收冷熱分離做的還不夠好,導(dǎo)致回收效率低

1匿名內(nèi)存和文件內(nèi)存的各自特點

1)匿名內(nèi)存

內(nèi)核認(rèn)為匿名內(nèi)存大部分都是active的,不會有太多used once或者short-lived的匿名內(nèi)存。

就是說內(nèi)核假定:匿名內(nèi)存,比如malloc,一旦被用戶創(chuàng)建出來分配好對應(yīng)的物理內(nèi)存,那么該塊物理內(nèi)存就會被頻繁使用,如果不被用的話,用戶會及時free該內(nèi)存的(否則的話,就算是內(nèi)存泄漏了)。

但是相機場景下,不好說,應(yīng)該會存在一些并不是被頻繁使用的匿名內(nèi)存,用戶創(chuàng)建出來后,是為全局考慮的,會出現(xiàn)有一段時間會頻繁使用,使用完并不釋放,而是過一段稍微長時間后,還會繼續(xù)用它。

2)文件內(nèi)存

內(nèi)核假定文件內(nèi)存里面有相當(dāng)一部分是used-once或者short-lived內(nèi)存(因為文件預(yù)讀會引入很多不必要內(nèi)存頁),當(dāng)然也有另外一部分是被頻繁使用的內(nèi)存,兩部分交織在一塊。

2 內(nèi)核對文件頁和匿名頁在inactive/active分離方面的處理方式

1)匿名內(nèi)存

因為內(nèi)核認(rèn)為匿名內(nèi)存普通都是hot/active的,只要該塊內(nèi)存存在,就會被頻繁用到的,所以把新創(chuàng)建的匿名頁加入到了active list上。

同時二次機會法也不適用它,在inactive list上,只要匿名page被用戶進(jìn)程訪問到了,就會被立刻晉升到active list上去。

同時inactive_list_is_low函數(shù)里面也規(guī)定了active list長度要大于inactive的,另外重要的是匿名頁也沒有做working-set識別,轉(zhuǎn)換和保護(hù)。

2)文件內(nèi)存

上面說的其實是文件內(nèi)存里面都是inactive和active內(nèi)存頁混合在一起,所以內(nèi)核認(rèn)為文件內(nèi)存不一定都是active的,所以新創(chuàng)建的文件內(nèi)存就會被加入到inactive list上去,

然后進(jìn)行進(jìn)一步地通過二次機會法來進(jìn)行篩選,把頻繁訪問的,即active內(nèi)存晉升到active list上去,inactive的則被留下在內(nèi)存不足時優(yōu)先被回收掉。

這樣隨著事件的推移,進(jìn)程的working-set內(nèi)存頁就會幾乎全部集中在active list,而不會出現(xiàn)used-once/short-lived這種inactive內(nèi)存跑到active list上,給進(jìn)程內(nèi)存頁的冷熱分離帶來困難。

這樣進(jìn)程的working-set內(nèi)存頁就會被建立起來,并且不容易被內(nèi)存不足時回收掉。

另外進(jìn)程的working-set在特定時間段內(nèi)是固定的,但是時間長了,肯定會切換到另外一個working-set里面。

在working-set切換時,文件頁有refault distance算法來防止出現(xiàn)切換后,頻繁出現(xiàn)page thrashing.

3 最后結(jié)論

文件頁回收有很多優(yōu)化算法在保證盡量做到冷熱分離和減小page thrashing,但是匿名頁卻沒有這些算法保證,所以匿名頁回收效率感覺比文件頁低,導(dǎo)致的一個不好影響就是匿名頁發(fā)生的page thrashing應(yīng)該比較多于文件頁。

具體僅僅這里是通過代碼分析發(fā)現(xiàn)的,還得通過實驗數(shù)據(jù)驗證。

四、 內(nèi)核的內(nèi)存回收從來都是被動的回收

1 具體特點

1) 內(nèi)存回收都是內(nèi)存分配不能滿足需求時,才不得不陷入到slow path分配中做回收,這樣對內(nèi)存分配性能是會有差的影響的。

2) 就算陷入到slow path中,觸發(fā)的kswapd線程,也是在balance式地回收,只要內(nèi)存水位稍微達(dá)到一定閥值,內(nèi)存處于balanced狀態(tài)后,就停止工作了。

3) 內(nèi)存頁面的老化,只有在lru list被scan時,才會老化。也就是說LRU里面的老化時間流逝跟自然時間是沒有關(guān)系的。

掃描才是推動歷史車輪前進(jìn)的動力。而掃描又是由于達(dá)不到balanced而被觸發(fā)的,可見頁面老化的速度跟系統(tǒng)中內(nèi)存的緊缺程度是相關(guān)的。

內(nèi)存緊缺的時候,1分鐘前才被訪問過的頁面可能都不會被視作活躍;反過來,如果內(nèi)存不緊缺,長期不需要進(jìn)行回收,那么幾小時前訪問過的頁面又可能都會被視作活躍,并且在這段時間內(nèi)被訪問過一次和被訪問過多次的頁面會被同等對待

看過內(nèi)存回收二次機會法,才會對這個點有深入理解。

4) 目前的防止出現(xiàn)內(nèi)存thrashing而做的workingset保護(hù),只是保護(hù)了文件頁,匿名頁還未進(jìn)行保護(hù)(好像內(nèi)核5.9版本上才有)。其實匿名頁也需要進(jìn)行workingset保護(hù),減小thrashing。

2 導(dǎo)致的問題

移動設(shè)備相機場景下,經(jīng)常有突發(fā)性的高峰值內(nèi)存分配需求出現(xiàn)。如果還是上面這種內(nèi)存回收特點的話,是會導(dǎo)致相機內(nèi)存分配性能差,從而出現(xiàn)用戶操作卡頓,殺后臺現(xiàn)象比較嚴(yán)重。

3 解決方法

制定相機場景下的殺進(jìn)程管理策略,還有主動內(nèi)存回收策略,從而釋放整機內(nèi)存壓力,優(yōu)化相機內(nèi)存分配性能。



審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 嵌入式系統(tǒng)
    +關(guān)注

    關(guān)注

    40

    文章

    3520

    瀏覽量

    128805
  • cpu
    cpu
    +關(guān)注

    關(guān)注

    68

    文章

    10702

    瀏覽量

    209361
  • LINUX內(nèi)核
    +關(guān)注

    關(guān)注

    1

    文章

    315

    瀏覽量

    21556

原文標(biāo)題:使用內(nèi)存回收技術(shù)對嵌入式系統(tǒng)進(jìn)行性能優(yōu)化

文章出處:【微信號:LinuxDev,微信公眾號:Linux閱碼場】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    嵌入式linux開發(fā)的基本步驟有哪些?

    嵌入式Linux開發(fā)是一個復(fù)雜的過程,涉及到硬件選擇、操作系統(tǒng)移植、驅(qū)動開發(fā)、應(yīng)用程序開發(fā)等多個方面。以下是嵌入式Linux開發(fā)的基本步驟,
    的頭像 發(fā)表于 09-02 09:11 ?180次閱讀

    嵌入式linux開發(fā)板怎么操作

    嵌入式Linux開發(fā)板是一種基于Linux操作系統(tǒng)嵌入式系統(tǒng)開發(fā)平臺。它通常包括一個處理器、
    的頭像 發(fā)表于 09-02 09:09 ?201次閱讀

    嵌入式linux開發(fā)板芯片的工作原理

    了處理器、存儲器、輸入/輸出接口等硬件資源的嵌入式系統(tǒng)開發(fā)平臺。它通常采用Linux操作系統(tǒng)作為底層軟件平臺,提供了豐富的開發(fā)工具和庫函數(shù),方便開發(fā)者進(jìn)行
    的頭像 發(fā)表于 09-02 09:07 ?172次閱讀

    學(xué)習(xí)hypervisor嵌入式產(chǎn)品安全設(shè)計

    Hypervisor的設(shè)計與實現(xiàn),涵蓋嵌入式Hypervisor架構(gòu)與核心組件、中斷隔離技術(shù)、內(nèi)存隔離技術(shù)、循環(huán)表調(diào)度器、健康監(jiān)控、分區(qū)間通信技術(shù)、內(nèi)核資源管理模型、系統(tǒng)初始化過程、
    發(fā)表于 08-25 09:11

    嵌入式機電一體化系統(tǒng)設(shè)計與實現(xiàn)》讀后感

    更為深刻的理解。這本書不僅理論扎實,而且實踐強,通過詳細(xì)的案例分析和操作步驟,為讀者展現(xiàn)了一個完整的設(shè)計和實現(xiàn)流程。 首先,本書開篇即對嵌入式系統(tǒng)進(jìn)行了全面的概述,讓我對“嵌入”這一
    發(fā)表于 08-21 08:45

    基于嵌入式Linux內(nèi)核的Android操作系統(tǒng)智能移動終端

    電子發(fā)燒友網(wǎng)站提供《基于嵌入式Linux內(nèi)核的Android操作系統(tǒng)智能移動終端.pdf》資料免費下載
    發(fā)表于 11-06 10:07 ?0次下載
    基于<b class='flag-5'>嵌入式</b><b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>的Android操作<b class='flag-5'>系統(tǒng)</b>智能移動終端

    基于嵌入式Linux的無線多媒體傳輸系統(tǒng)設(shè)計與實現(xiàn)

    電子發(fā)燒友網(wǎng)站提供《基于嵌入式Linux的無線多媒體傳輸系統(tǒng)設(shè)計與實現(xiàn).pdf》資料免費下載
    發(fā)表于 10-26 14:37 ?0次下載
    基于<b class='flag-5'>嵌入式</b><b class='flag-5'>Linux</b>的無線多媒體傳輸<b class='flag-5'>系統(tǒng)</b>設(shè)計與實現(xiàn)

    基于嵌入式Linux智能家居監(jiān)控系統(tǒng)設(shè)計

    電子發(fā)燒友網(wǎng)站提供《基于嵌入式Linux智能家居監(jiān)控系統(tǒng)設(shè)計.pdf》資料免費下載
    發(fā)表于 10-25 10:02 ?1次下載
    基于<b class='flag-5'>嵌入式</b><b class='flag-5'>Linux</b>智能家居監(jiān)控<b class='flag-5'>系統(tǒng)</b>設(shè)計

    基于ARM Linux和S3C2440的嵌入式Linux內(nèi)核設(shè)計

    電子發(fā)燒友網(wǎng)站提供《基于ARM Linux和S3C2440的嵌入式Linux內(nèi)核設(shè)計.pdf》資料免費下載
    發(fā)表于 10-12 10:37 ?2次下載
    基于ARM <b class='flag-5'>Linux</b>和S3C2440的<b class='flag-5'>嵌入式</b><b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>設(shè)計

    基于嵌入式Linux系統(tǒng)的MiniGUI的移植

    電子發(fā)燒友網(wǎng)站提供《基于嵌入式Linux系統(tǒng)的MiniGUI的移植.pdf》資料免費下載
    發(fā)表于 10-12 10:20 ?1次下載
    基于<b class='flag-5'>嵌入式</b><b class='flag-5'>Linux</b><b class='flag-5'>系統(tǒng)</b>的MiniGUI的移植

    基于ARM9內(nèi)核嵌入式檢測系統(tǒng)設(shè)計

    電子發(fā)燒友網(wǎng)站提供《基于ARM9內(nèi)核嵌入式檢測系統(tǒng)設(shè)計.pdf》資料免費下載
    發(fā)表于 10-12 09:48 ?0次下載
    基于ARM9<b class='flag-5'>內(nèi)核</b>的<b class='flag-5'>嵌入式</b>檢測<b class='flag-5'>系統(tǒng)</b>設(shè)計

    什么是嵌入式Linux?

    Linux到底是什么呢? 嵌入式linux 是將日益流行的Linux操作系統(tǒng)進(jìn)行裁剪修改,使之能在嵌入式
    發(fā)表于 10-11 13:47

    基于Linux嵌入式視覺系統(tǒng)設(shè)計原理

    電子發(fā)燒友網(wǎng)站提供《基于Linux嵌入式視覺系統(tǒng)設(shè)計原理.pdf》資料免費下載
    發(fā)表于 10-11 11:26 ?0次下載
    基于<b class='flag-5'>Linux</b>的<b class='flag-5'>嵌入式</b>視覺<b class='flag-5'>系統(tǒng)</b>設(shè)計原理

    嵌入式Linux在磁場測量系統(tǒng)中的應(yīng)用

    電子發(fā)燒友網(wǎng)站提供《嵌入式Linux在磁場測量系統(tǒng)中的應(yīng)用.pdf》資料免費下載
    發(fā)表于 10-11 10:11 ?0次下載
    <b class='flag-5'>嵌入式</b><b class='flag-5'>Linux</b>在磁場測量<b class='flag-5'>系統(tǒng)</b>中的應(yīng)用

    嵌入式Linux應(yīng)用開發(fā)的完全手冊

    嵌入式Linux嵌入式領(lǐng)域發(fā)展迅速、需求旺盛,但是嵌入式Linux 的入門很難。初學(xué)者多是自己琢磨,效率不高。學(xué)習(xí)過程中碰到的問題千奇百怪
    發(fā)表于 09-25 07:12