—— 在各種帖子中,我們經常能看到類似說 “記憶體用的多才正常,記憶體就是拿來用的,搞精簡剩那麼多記憶體在那幹嘛?” 的言論。 這些言論或多或少缺乏嚴謹性。 下面我會盡可能用較為簡單的描述讓各位對自己手機的記憶體管理(主要是虛擬記憶體)有個基本的認識,新人第一次寫科普,如有錯誤還請各位大佬在評論區指出
—————分割線—————
注:本文中所有的「記憶體」均指人們常說的「運行記憶體」也就是「RAM」而非存儲空間!
—————分割線—————
首先,我們來認識一些概念和專業名詞
1.虛擬記憶體:
虛擬記憶體是現代操作系統普遍使用的一種記憶體管理技術,目前常用的是頁式虛擬記憶體管理,以頁(通常是4KB)為最小粒度來管理記憶體的分配、回收、交換等。
2.SWAP:
SWAP是虛擬記憶體技術的一部分,在硬碟上劃分空間用於交換記憶體頁,說人話就是把記憶體中的數據移動到硬碟上以騰出物理記憶體。 Windows上也有類似的功能「分頁檔」。 但與Linux不同的是,Windows對分頁檔是強依賴的,關掉會有大問題,詳情見本文末尾的番外篇。
3.ZRAM:
ZRAM是SWAP的另一種實現,不在硬碟空間而是直接在記憶體中劃分空間用來交換記憶體頁,使用LZ4/ZSTD等壓縮演算法對記憶體數據進行壓縮以騰出物理記憶體。
4.ZRAM Writeback
ZRAM Writeback是ZRAM的拓展功能,與SWAP一樣會在硬碟空間上創建交換檔用於交換記憶體頁,不同的點在於ZRAM Writeback交換的是壓縮后的記憶體數據。 寫入控制邏輯運行在用戶層而非內核中,具體策略由系統廠商決定,故本文不做討論。
5.直接回收與異步回收
記憶體回收的兩種方式,異步回收在後台線程運行,不影響當前進程,對性能和流暢度影響較小,但回收速度慢; 直接回收速度快,但會阻塞當前進程,實際表現為軟體介面卡住一段時間(通常很短),對性能和流暢度影響較大。
—————分割線—————
首先來回答標題的「記憶體用的越多越好? “,這句話對嗎? 對,但不全對。
記憶體確實是拿來用的,但要知道一點,要用記憶體的並不只有操作系統和使用者的軟體,還有一個大頭就是檔緩存,幾乎所有操作系統都有檔緩存機制,從硬碟/快閃記憶體中讀取的檔會緩存在記憶體中,下次調用時就不需要再從硬碟/快閃記憶體讀取而是直接調用檔緩存以加快速度。 在記憶體不足時文件緩存能夠被快速釋放騰出記憶體以供分配,因此這些能夠快速回收的記憶體與空閑記憶體均被內核當做「可用記憶體」。。 而你在系統後檯介面和各個軟體(如DEV Check)中看到的都不是“空閑記憶體”而是內核計算得出的“可用記憶體”或軟體自身演演算法計算得出的“可用記憶體”。
如圖在內核的meminfo中“可用記憶體”≠“空閑記憶體”,“空閒記憶體”是真正沒有被任何進程或檔所佔用的未分配的記憶體,而“可用記憶體”則是可用於分配的記憶體(其大小是一個估測值,主要由檔緩存和空閒記憶體中Low水位線以上的部分以及其它可快速回收的記憶體項決定)

數據來源:/proc/meminfo
所以即便你在系統後台的記憶體資訊或各軟體中看到記憶體還剩很多,那也並不能代表記憶體沒得到充分利用。 而搞精簡搞優化的那部分人比如我追求的則是降低系統自身的記憶體佔用,好騰出更多記憶體供使用者應用使用,與“記憶體用的多才正常,記憶體就是拿來用的”的觀點並不衝突。
—————分割線—————
進階教程——控制記憶體回收與ZRAM的積極性:
在擁有ROOT許可權的前提下,我們可以修改以下內核參數來控制記憶體回收與ZRAM的積極性。
1. vm.watermark_scale_factor:
控制記憶體水位線之間的間隔,調節範圍為1~1000(對應0.01%至10%的總記憶體大小)。 值太小會頻繁觸發直接回收導致卡頓,值太大會造成記憶體浪費,建議設置為100(總記憶體的1%)。
內核定義了min/low/high三條水位線,當空閒記憶體(注意是“空閑記憶體”而不是“可用記憶體”)低於low水位線時內核就會喚醒kswapd異步回收記憶體(將數據交換至ZRAM/SWAP並回收檔緩存),直到空閒記憶體高於high水位線就停止; 當空閒記憶體低於min水位線時會觸發直接回收。 min水位線的值由內核根據總記憶體大小與vm.min_free_kbytes計算比較得出,不建議修改該參數保持預設值就好。
2. vm.extra_free_kbytes:
額外保留的記憶體,會在min和low水位線之間增加設定的值,值太小會頻繁觸發直接回收導致卡頓,值太大會造成記憶體浪費,建議設置為總記憶體大小的1~2%,以KB為單位。
3. vm.swappiness:
控制內核記憶體不足時(低於low水位線)在交換頁面至ZRAM/SWAP與回收檔緩存之間的偏向,值的範圍為0~200,對於老內核範圍為0~100。 值越小越傾向於回收文件緩存,值越大越傾向於使用ZRAM/SWAP。
以上內核參數可在Scene中修改,也可以root許可權執行以下命令修改:
echo 100 >/proc/sys/vm/watermark_scale_factor
echo 131072 >/proc/sys/vm/extra_free_kbytes
echo 100 >/proc/sys/vm/swappiness

– 如果你追求保留更多的後台,可降低extra_free_kbytes與watermark_scale_factor的值,適量增大swappiness的值。
– 如果你追求更高的流暢度,可增加extra_free_kbytes與watermark_scale_factor的值,同時將swappiness調整到較為平衡的值。
– 如果你既要又要,那就換記憶體更大的手機
—————分割線—————
LMK與殺後台:
從Android 9起,Google開始拋棄內核自帶的LMK轉為使用作為系統守護進程運行的LMKD,因此殺後台與內核本身關係就不大了,主要取決於各廠商怎麼配置LMKD/引入其它殺後台機制。 對於MIUI而言,除了配置LMKD外,在「電量與性能」與「framework系統框架」中均有殺後台相關代碼。 如果你不想用廠商額外引入的殺後台機制想自己配置LMKD,那麼可用使用LSPosed模組“AppRetention”來遮罩廠商的殺後台機制。

然後根據Google的文件來配置LMKD:查看連結

—————分割線—————
番外篇——有關Windows分頁檔Pagefile.sys與虛擬記憶體位址分配的額外知識:
Windows採用兩階段記憶體分配(保留+提交),在提交階段必須確保物理位址(物理記憶體或分頁檔)的映射。 分頁檔作為系統提交限制的組成部分,直接決定了系統可支援的虛擬記憶體總量(在Windows任務管理器的記憶體資訊卡頁面上有“已提交”這個數據項,斜杠左側是所有程式申請的記憶體大小之和,右側是總虛擬記憶體大小,其值=物理記憶體大小+分頁檔大小,其中分頁檔由系統動態劃分)

Windows任務管理器的記憶體資訊
你可以簡單認為在Windows上程式申請多少記憶體系統就會把對應大小的物理位址劃分給程式,劃分后其它程式就無法使用這片記憶體空間,而程式申請的記憶體大小又普遍高於其實際用到的大小,因此在關閉分頁文件的情況下會出現物理記憶體還剩很多但打開新的程式仍提示記憶體不足的情況。 而在Linux上則沒這個問題,Linux採用延遲分配策略,僅當進程實際訪問記憶體時才分配物理記憶體位址,至於程式申請的記憶體Linux則是分配的“真”虛擬位址,虛擬記憶體位址的限制則是由“vm.overcommit_memory”內核參數決定,在我們所用的Android手機上虛擬記憶體的分配限制“overcommit_memory” 默認值為1,也就是無視虛擬記憶體限制允許分配全部物理記憶體。
在Scene的SWAP管理頁面可以看到我手機上所有進程申請的記憶體大小高達208GB! 但物理記憶體沒用完因此我還可以繼續開新的軟體。

至於為什麼Windows不改成跟Linux一樣或類似的機制那我也不知道,只能認為是Windows的歷史包袱太重了(與之對應的是WIN的傳奇級相容性)




![[圖文匯總]目前支援5G-A載波聚合的終端匯總---附iOS下查看載波聚合是否啟用的方法-白雲博客](https://www.bybk.cc/wp-content/uploads/2024/04/20240407140712630-e26ee861710dd3b075a1302dd00392d5e1db60a1.jpeg)







暫無評論內容