具體概念,在《Linux Kernel elementary Knowledge》中都有介紹。
影響也很簡單:1、性能問題,大塊的連續(xù)內(nèi)存分配不到或者時間很長,導(dǎo)致卡頓。
2、浪費,大量內(nèi)存碎片化了無法利用。
3、為了整理內(nèi)存,kswapd和kcompactd頻繁喚醒,占CPU,影響功耗。
尤其是相機、ion和gpu內(nèi)存分配,都有分配連續(xù)物理內(nèi)存的需求,ion是按8/9->4->0階分配的,kernel-4.14之前的版本內(nèi)核棧的16K都是連續(xù)的order=2的物理內(nèi)存。
用戶態(tài)有了MMU和頁表,其實碎片化問題就很小了,缺頁異常的時候多搞些離散的頁面拼一拼就行了,主要還是內(nèi)核態(tài)的問題。
簡單講下優(yōu)化的一些思路:
1、雖然kernel-4.14開始內(nèi)核棧用使用vmalloc分配,不過之前的版本,可以提前預(yù)留order = 2的頁面供內(nèi)核線程分配。kernelstack一般不超過250M,可以按這個size去配置適當(dāng)?shù)念A(yù)留內(nèi)存。
或者打開這個宏CONFIG_VMAP_STACK = y
2、ion_boost_pool 給ion分配做個pool
ion驅(qū)動里面申請的內(nèi)存頁面都是unmoveable的,更容易造成碎片問題。系統(tǒng)內(nèi)存充足或者壓力小時,就相機每次分配完ion內(nèi)存后,就會觸發(fā)下該緩存池的蓄水工作,會在系統(tǒng)里面再搞出很多連續(xù)free頁面,加到該池子里面。那么下次再分配ion內(nèi)存時,直接從池子里面取,這個pool的size最好是可配的,一般512M才會有明顯效果,128效果非常有限。
這樣每次ion內(nèi)存分配都會聚合在一個地方(page pool)進行分配, unmoveable頁面都會聚合在一起,不會再發(fā)散地分布在系統(tǒng)內(nèi)存各個地方。然后等到系統(tǒng)的內(nèi)存分配壓力大時,這個page pool里面的緩存隨時都可以被釋放出來,滿足系統(tǒng)其他地方的內(nèi)存分配請求。詳見代碼:kernel/msm-4.19/drivers/staging/android/ion/ion_page_pool.c
3、kvmalloc()中,當(dāng)分配size超過N個page,直接return到vmalloc,減少連續(xù)kmalloc的分配。
4、boost watermark 臨時提高水位,并提前喚醒kswapd,防止外碎片化進一步惡化
限制內(nèi)核page cache使用,雖然調(diào)大 vm.min_free_kbytes 確實會導(dǎo)致一些內(nèi)存浪。但是旗艦手機總內(nèi)存本身就大,內(nèi)存充足,這個時候重點關(guān)注的是碎片化問題,那么就上boost watermark方案優(yōu)化碎片。
5、最強優(yōu)化,可以優(yōu)化99%內(nèi)存碎片化,保密哈哈~