溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Android對Linux系統(tǒng)的內(nèi)存管理機(jī)制進(jìn)行的優(yōu)化是什么

發(fā)布時(shí)間:2021-11-30 09:53:42 來源:億速云 閱讀:129 作者:iii 欄目:大數(shù)據(jù)

這篇文章主要介紹“Android對Linux系統(tǒng)的內(nèi)存管理機(jī)制進(jìn)行的優(yōu)化是什么”,在日常操作中,相信很多人在Android對Linux系統(tǒng)的內(nèi)存管理機(jī)制進(jìn)行的優(yōu)化是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Android對Linux系統(tǒng)的內(nèi)存管理機(jī)制進(jìn)行的優(yōu)化是什么”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

Android對內(nèi)存的使用方式同樣是“盡最大限度的使用”,這一點(diǎn)繼承了Linux的優(yōu)點(diǎn)。只不過有所不同的是,Linux側(cè)重于盡可能多的緩存磁盤數(shù)據(jù)以降低磁盤IO進(jìn)而提高系統(tǒng)的數(shù)據(jù)訪問性能,而 Android側(cè)重于盡可能多的緩存進(jìn)程以提高應(yīng)用啟動和切換速度。Linux系統(tǒng)在進(jìn)程活動停止后就結(jié)束該進(jìn)程,而Android系統(tǒng)則會在內(nèi)存中盡量長時(shí)間的保持應(yīng)用進(jìn)程,直到系統(tǒng)需要更多內(nèi)存為止 。這些保留在內(nèi)存中的進(jìn)程,通常情況下不會影響系統(tǒng)整體運(yùn)行速度,反而會在用戶再次激活這些進(jìn)程時(shí),加快進(jìn)程的啟動速度,因?yàn)椴挥弥匦录虞d界面資源了,這是Android標(biāo)榜的特性之一。所以,Android現(xiàn)在不推薦顯式的“退出”應(yīng)用。

那為什么內(nèi)存少的時(shí)候運(yùn)行大型程序會慢呢,原因是:在內(nèi)存剩余不多時(shí)打開大型程序會觸發(fā)系統(tǒng)自身的進(jìn)程調(diào)度策略,這是十分消耗系統(tǒng)資源的操作,特別是在一個(gè)程序頻繁向系統(tǒng)申請內(nèi)存的時(shí)候。這種情況下系統(tǒng)并不會關(guān)閉所有打開的進(jìn)程,而是選擇性關(guān)閉,頻繁的調(diào)度自然會拖慢系統(tǒng)。 

Android中的進(jìn)程管理

說到Android的內(nèi)存管理,就不得不提到進(jìn)程管理,因?yàn)檫M(jìn)程管理確確切切的影響著系統(tǒng)內(nèi)存。在了解進(jìn)程管理之前,我們首先了解一些基礎(chǔ)概念。

當(dāng)某個(gè)應(yīng)用組件啟動且該應(yīng)用沒有運(yùn)行其他任何組件時(shí),Android 系統(tǒng)會使用單個(gè)執(zhí)行線程為應(yīng)用啟動新的 Linux 進(jìn)程。默認(rèn)情況下,同一應(yīng)用的所有組件在相同的進(jìn)程和線程(稱為“主”線程) 中運(yùn)行。如果某個(gè)應(yīng)用組件啟動且該應(yīng)用已存在進(jìn)程(因?yàn)榇嬖谠搼?yīng)用的其他組件),則該組件會在此進(jìn)程內(nèi)啟動并使用相同的執(zhí)行線程。但是,你也可以安排應(yīng)用中的其他組件在單獨(dú)的進(jìn)程中運(yùn)行,并為任何進(jìn)程創(chuàng)建額外的線程。

Android應(yīng)用模型的設(shè)計(jì)思想取自Web 2.0的Mashup概念,是 基于組件的應(yīng)用設(shè)計(jì)模式。在該模型下,每個(gè)應(yīng)用都由一系列的組件搭建而成,組件通過應(yīng)用的配置文件描述功能。Android系統(tǒng)依照組件的配置信息,了解各個(gè)組件的功能并進(jìn)行統(tǒng)一調(diào)度。這就意味著,來自不同應(yīng)用的組件可以有機(jī)地結(jié)合在一起,共同完成任務(wù),各個(gè)Android應(yīng)用,只有明確的組件邊界,而不再有明確的進(jìn)程邊界和應(yīng)用邊界。這種設(shè)計(jì),也令得開發(fā)者無需耗費(fèi)精力去重新開發(fā)一些附屬功能,而是可以全身心地投入到核心功能的開發(fā)中。這樣不但提高了應(yīng)用開發(fā)的效率,也增強(qiáng)了用戶體驗(yàn)(比如電子郵件中選擇圖片作為附件的功能,可以直接調(diào)用專門的圖片應(yīng)用的功能,不用自己從頭開發(fā))。

系統(tǒng)不會為每個(gè)組件實(shí)例創(chuàng)建單獨(dú)的線程。運(yùn)行于同一進(jìn)程的所有組件均在 UI 線程中實(shí)例化,并且對每個(gè)組件的系統(tǒng)調(diào)用均由該線程進(jìn)行分派。 因此,響應(yīng)系統(tǒng)回調(diào)的方法(例如,報(bào)告用戶操作的 onKeyDown() 或生命周期回調(diào)方法)始終在進(jìn)程的 UI 線程中運(yùn)行(四大組件的各個(gè)生命周期回調(diào)方法都是在UI線程中觸發(fā)的)。 

進(jìn)程的生命周期

Android的一個(gè)不尋常的基本特征是應(yīng)用程序進(jìn)程的生命周期并非是由應(yīng)用本身直接控制的。相反,進(jìn)程的生命周期是由系統(tǒng)決定的,系統(tǒng)會權(quán)衡每個(gè)進(jìn)程對用戶的相對重要程度,以及系統(tǒng)的可用內(nèi)存總量來確定。 比如說相對于終止一個(gè)托管了正在與用戶交互的Activity的進(jìn)程,系統(tǒng)更可能終止一個(gè)托管了屏幕上不再可見的Activity的進(jìn)程,否則這種后果是可怕的。因此,是否終止某個(gè)進(jìn)程取決于該進(jìn)程中所運(yùn)行組件的狀態(tài) 。Android會有限清理那些已經(jīng)不再使用的進(jìn)程,以保證最小的副作用。

作為應(yīng)用開發(fā)者,了解各個(gè)應(yīng)用組件(特別是Activity、Service和BroadcastReceiver)如何影響應(yīng)用進(jìn)程的生命周期非常重要。不正確的使用這些組件,有可能導(dǎo)致系統(tǒng)在應(yīng)用執(zhí)行重要工作時(shí)終止進(jìn)程。

舉個(gè)常見的例子, BroadcastReceiver 在其 onReceive() 方法中接收到Intent時(shí)啟動一個(gè)線程,然后從該函數(shù)返回。而一旦返回,系統(tǒng)就認(rèn)為該 BroadcastReceiver 不再處于活動狀態(tài),因此也就不再需要其托管進(jìn)程(除非該進(jìn)程中還有其他組件處于活動狀態(tài))。這樣一來,系統(tǒng)就有可能隨時(shí)終止進(jìn)程以回收內(nèi)存,而這也最終會導(dǎo)致運(yùn)行在進(jìn)程中的線程被終止。此問題的解決方案通常是從 BroadcastReceiver 中安排一個(gè) JobService ,以便系統(tǒng)知道在該進(jìn)程中仍有活動的工作。

為了確定在內(nèi)存不足時(shí)終止哪些進(jìn)程,Android會根據(jù)進(jìn)程中正在運(yùn)行的組件以及這些組件的狀態(tài),將每個(gè)進(jìn)程放入 “重要性層次結(jié)構(gòu)” 中。必要時(shí),系統(tǒng)會首先殺死重要性最低的進(jìn)程,以此類推,以回收系統(tǒng)資源。這就相當(dāng)于為進(jìn)程分配了優(yōu)先級的概念。 

進(jìn)程優(yōu)先級

Foreground Process:前臺進(jìn)程(正常不會被殺死)

用戶當(dāng)前操作所必需的進(jìn)程。有很多組件能以不同的方式使得其所在進(jìn)程被判定為前臺進(jìn)程。如果一個(gè)進(jìn)程滿足以下任一條件,即視為前臺進(jìn)程:

  • 托管用戶正在交互的 Activity(已調(diào)用 Activity 的 onResume() 方法)

  • 托管某個(gè) Service,后者綁定到用戶正在交互的 Activity

  • 托管正執(zhí)行一個(gè)生命周期回調(diào)的 Service(onCreate()、onStart() 或 onDestroy())

  • 托管正執(zhí)行其 onReceive() 方法的 BroadcastReceiver

通常,在任意給定時(shí)間前臺進(jìn)程都為數(shù)不多。只有在內(nèi)存不足以支持它們同時(shí)繼續(xù)運(yùn)行這一萬不得已的情況下,系統(tǒng)才會終止它們。此時(shí),設(shè)備往往已達(dá)到內(nèi)存分頁狀態(tài),因此需要終止一些前臺進(jìn)程來確保用戶界面正常響應(yīng)。

Visible Process:可見進(jìn)程(正常不會被殺死

沒有任何前臺組件、但仍會影響用戶在屏幕上所見內(nèi)容的進(jìn)程。殺死這類進(jìn)程也會明顯影響用戶體驗(yàn)。如果一個(gè)進(jìn)程滿足以下任一條件,即視為可見進(jìn)程:

  • 托管不在前臺、但仍對用戶可見的 Activity(已調(diào)用其 onPause() 方法)。例如,啟動了一個(gè)對話框樣式的前臺 activity ,此時(shí)在其后面仍然可以看到前一個(gè)Activity。

運(yùn)行時(shí)權(quán)限對話框就屬于此類??紤]一下,還有哪種情況會導(dǎo)致只觸發(fā)onPause而不觸發(fā)onStop?

  • 托管通過 Service.startForeground() 啟動的前臺Service。

Service.startForeground():它要求系統(tǒng)將它視為用戶可察覺到的服務(wù),或者基本上對用戶是可見的。

  • 托管系統(tǒng)用于某個(gè)用戶可察覺的特定功能的Service,比如動態(tài)壁紙、輸入法服務(wù)等等。

可見進(jìn)程被視為是極其重要的進(jìn)程,除非為了維持所有前臺進(jìn)程同時(shí)運(yùn)行而必須終止,否則系統(tǒng)不會終止這些進(jìn)程。如果這類進(jìn)程被殺死,從用戶的角度看,這意味著當(dāng)前 activity 背后的可見 activity 會被黑屏代替。

Service Process:服務(wù)進(jìn)程(正常不會被殺死)

正在運(yùn)行已使用 startService() 方法啟動的服務(wù)且不屬于上述兩個(gè)更高類別進(jìn)程的進(jìn)程。盡管服務(wù)進(jìn)程與用戶所見內(nèi)容沒有直接關(guān)聯(lián),但是它們通常在執(zhí)行一些用戶關(guān)心的操作(例如,后臺網(wǎng)絡(luò)上傳或下載數(shù)據(jù))。因此,除非內(nèi)存不足以維持所有前臺進(jìn)程和可見進(jìn)程同時(shí)運(yùn)行,否則系統(tǒng)會讓服務(wù)進(jìn)程保持運(yùn)行狀態(tài)。

已經(jīng)運(yùn)行很久(例如30分鐘或更久)的Service,有可能被降級,這樣一來它們所在的進(jìn)程就可以被放入Cached LRU列表中。這有助于避免一些長時(shí)間運(yùn)行的Service由于內(nèi)存泄漏或其他問題而消耗過多的RAM,進(jìn)而導(dǎo)致系統(tǒng)無法有效使用緩存進(jìn)程的情況。

Background / Cached Process:后臺進(jìn)程(可能隨時(shí)被殺死)

這類進(jìn)程一般會持有一個(gè)或多個(gè)目前對用戶不可見的 Activity (已調(diào)用 Activity 的 onStop() 方法)。它們不是當(dāng)前所必須的,因此當(dāng)其他更高優(yōu)先級的進(jìn)程需要內(nèi)存時(shí),系統(tǒng)可能 隨時(shí)終止 它們以回收內(nèi)存。但如果正確實(shí)現(xiàn)了Activity的生命周期,即便系統(tǒng)終止了進(jìn)程,當(dāng)用戶再次返回應(yīng)用時(shí)也不會影響用戶體驗(yàn):關(guān)聯(lián)Activity在新的進(jìn)程中被重新創(chuàng)建時(shí)可以恢復(fù)之前保存的狀態(tài)。

在一個(gè)正常運(yùn)行的系統(tǒng)中,緩存進(jìn)程是內(nèi)存管理中 唯一 涉及到的進(jìn)程:一個(gè)運(yùn)行良好的系統(tǒng)將始終具有多個(gè)緩存進(jìn)程(為了更高效的切換應(yīng)用),并根據(jù)需要定期終止最舊的進(jìn)程。只有在非常嚴(yán)重(并且不可?。┑那闆r下,系統(tǒng)才會到達(dá)這樣一個(gè)點(diǎn),此時(shí)所有的緩存進(jìn)程都已被終止,并且必須開始終止服務(wù)進(jìn)程。

Android系統(tǒng)回收后臺進(jìn)程的參考條件:

  • LRU算法:自下而上開始終止,先回收最老的進(jìn)程。越老的進(jìn)程近期內(nèi)被用戶再次使用的幾率越低。殺死的進(jìn)程越老,對用戶體驗(yàn)的影響就越小。

  • 回收收益:系統(tǒng)總是傾向于殺死一個(gè)能回收更多內(nèi)存的進(jìn)程,因?yàn)樵谒粴r(shí)會為系統(tǒng)提供更多內(nèi)存增益,從而可以殺死更少的進(jìn)程。殺死的進(jìn)程越少,對用戶體驗(yàn)的影響就越小。換句話說,應(yīng)用進(jìn)程在整個(gè)LRU列表中消耗的內(nèi)存越少,保留在列表中并且能夠快速恢復(fù)的機(jī)會就越大。

這類進(jìn)程會被保存在一個(gè)偽LRU列表中,系統(tǒng)會優(yōu)先殺死處于列表尾部(最老)的進(jìn)程,以確保包含用戶最近查看的 Activity 的進(jìn)程最后一個(gè)被終止。這個(gè)LRU列表排序的確切策略是平臺的實(shí)現(xiàn)細(xì)節(jié),但通常情況下,相對于其他類型的進(jìn)程,系統(tǒng)會優(yōu)先嘗試保留更有用的進(jìn)程(比如托管用戶主應(yīng)用程序的進(jìn)程,或者托管用戶看到的最后一個(gè)Activity的進(jìn)程,等等)。還有其他一些用于終止進(jìn)程的策略:對允許的進(jìn)程數(shù)量硬限制,對進(jìn)程可以持續(xù)緩存的時(shí)間量的硬限制,等等。

在一個(gè)健康的系統(tǒng)中,只有緩存進(jìn)程或者空進(jìn)程會被系統(tǒng)隨時(shí)終止,如果服務(wù)進(jìn)程,或者更高優(yōu)先級的可見進(jìn)程以及前臺進(jìn)程也開始被系統(tǒng)終止(不包括應(yīng)用本身糟糕的內(nèi)存使用導(dǎo)致OOM),那就說明系統(tǒng)運(yùn)行已經(jīng)處于一個(gè)亞健康甚至極不健康的狀態(tài),可用內(nèi)存已經(jīng)吃緊。

Empty Process:空進(jìn)程(可以隨時(shí)殺死)

不含任何活躍組件的進(jìn)程。保留這種進(jìn)程的的唯一目的是用作緩存(為了更加有效的使用內(nèi)存而不是完全釋放掉),以縮短下次啟動應(yīng)用程序所需的時(shí)間,因?yàn)閱右粋€(gè)新的進(jìn)程也是需要代價(jià)的。只要有需要,Android會隨時(shí)殺死這些進(jìn)程。

內(nèi)存管理中對于前臺/后臺應(yīng)用的定義,與用于Service限制目的的后臺應(yīng)用定義不同。從Android 8.0開始,出于節(jié)省系統(tǒng)資源、優(yōu)化用戶體驗(yàn)、提高電池續(xù)航能力的考量,系統(tǒng)進(jìn)行了前臺/后臺應(yīng)用的區(qū)分,對于后臺service進(jìn)行了一些限制。在該定義中,如果滿足以下任意條件,應(yīng)用將被視為處于前臺:

>

  • 具有可見 Activity(不管該 Activity 已啟動還是已暫停)。

  • 具有前臺 Service。

  • 另一個(gè)前臺應(yīng)用已關(guān)聯(lián)到該應(yīng)用(不管是通過綁定到其中一個(gè) Service,還是通過使用其中一個(gè)內(nèi)容提供程序)。例如,如果另一個(gè)應(yīng)用綁定到該應(yīng)用的 Service,那么該應(yīng)用處于前臺:IME 壁紙 Service 通知偵聽器 語音或文本 Service 如果以上條件均不滿足,應(yīng)用將被視為處于后臺。 

Android系統(tǒng)如何評定進(jìn)程的優(yōu)先級

根據(jù)進(jìn)程中當(dāng)前活動組件的重要程度,Android 會將進(jìn)程評定為它可能達(dá)到的最高級別。 例如,如果某進(jìn)程同時(shí)托管著 Service 和可見 Activity,則會將此進(jìn)程評定為可見進(jìn)程,而不是服務(wù)進(jìn)程。

此外,一個(gè)進(jìn)程的級別可能會因其他進(jìn)程對它的依賴而有所提高,即服務(wù)于另一進(jìn)程的進(jìn)程其級別永遠(yuǎn)不會低于其所服務(wù)的進(jìn)程。 例如,如果進(jìn)程 A 中的內(nèi)容提供程序?yàn)檫M(jìn)程 B 中的客戶端提供服務(wù),或者如果進(jìn)程 A 中的服務(wù)綁定到進(jìn)程 B 中的組件,則進(jìn)程 A 始終被視為至少與進(jìn)程 B 同樣重要。

由于運(yùn)行服務(wù)的進(jìn)程其級別高于托管后臺 Activity 的進(jìn)程,因此,在 Activity 中啟動一個(gè)長時(shí)間運(yùn)行的操作時(shí),最好為該操作啟動服務(wù),而不是簡單地創(chuàng)建工作線程,當(dāng)操作有可能比 Activity 更加持久時(shí)尤要如此。例如,一個(gè)文件上傳的操作就可以考慮使用服務(wù)來完成,這樣一來,即使用戶退出 Activity,仍可在后臺繼續(xù)執(zhí)行上傳操作。使用服務(wù)可以保證,無論 Activity 發(fā)生什么情況,該操作至少具備“服務(wù)進(jìn)程”優(yōu)先級。同理, BroadcastReceiver 也應(yīng)使用服務(wù),而不是簡單地將耗時(shí)冗長的操作放入線程中。 

Home鍵退出和返回鍵退出的區(qū)別

Home鍵退出,程序保留狀態(tài)為后臺進(jìn)程;而返回鍵退出,程序保留狀態(tài)為空進(jìn)程,空進(jìn)程更容易被系統(tǒng)回收。Home鍵其實(shí)主要用于進(jìn)程間切換,返回鍵則是真正的退出程序。

從理論上來講,無論是哪種情況,在沒有任何后臺工作線程(即便應(yīng)用處于后臺,工作線程仍然可以執(zhí)行)的前提下,被置于后臺的進(jìn)程都只是保留他們的運(yùn)行狀態(tài),并不會占用CPU資源,所以也不耗電。只有音樂播放軟件之類的應(yīng)用需要在后臺運(yùn)行Service,而Service是需要占用CPU時(shí)間的,此時(shí)才會耗電。所以說沒有帶后臺服務(wù)的應(yīng)用是不耗電也不占用CPU時(shí)間的,沒必要關(guān)閉,這種設(shè)計(jì)本身就是Android的優(yōu)勢之一,可以讓應(yīng)用下次啟動時(shí)更快。然而現(xiàn)實(shí)是,很多應(yīng)用多多少少都會有一些后臺工作線程,這可能是開發(fā)人員經(jīng)驗(yàn)不足導(dǎo)致(比如線程未關(guān)閉或者循環(huán)發(fā)送的Handler消息未停止),也可能是為了需求而有意為之,導(dǎo)致整個(gè)Android應(yīng)用的生態(tài)環(huán)境并不是一片干凈。

到此,關(guān)于“Android對Linux系統(tǒng)的內(nèi)存管理機(jī)制進(jìn)行的優(yōu)化是什么”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI