為什麼 iPhone 5s 什麼程序也不開的情況下內存佔用高達 600 多 M?
為什麼蘋果5s內存在什麼程序也不開的情況下使用率仍然那麼高達到600多M,而且開再多程序不覺得卡。(附加問題:Windows的內存管理特色與之相反么?手機和桌面不同環境的內存管理策略差異大不大?)
某高票答案關於unix系內存管理的說法純屬胡說八道。
unix系用top之類命令看內存佔用時,會發現它比windows之類系統內存佔用更高;但這並不是什麼「惰性釋放內存」。真正的原因是:它會盡量把空閑內存拿來做緩存,以盡量減少外設訪問,提高性能表現。
如果你是linux/windows的老用戶,且經常切換使用linux/windows,就會發現,內存足夠且無磁碟相關操作時,windows系統的硬碟燈仍然不停閃爍,而linux卻可以幾分鐘甚至幾十分鐘都不閃一下。這就是cache演算法的威力。
PS:大概win7之後,windows也有了類似機制,於是情況大有改善,硬碟燈也能做到十幾秒才閃一次。
PS2:linux的確是不把buffers/cache空間報告為free內存空間的,見下面的鏈接;但buffers/cache中的一部分可視為free空間(即:如果程序申請更多內存,buffers/cache佔用的部分內存可釋放、然後分配給需要內存得程序使用)——之前我曾經很疑惑,為何linux內存管理明顯比windows xp好得多得多,但未啟動任何服務/進程的系統怎麼比windows的內存佔用量多那麼多?後來才知道是把cache也算做已用內存了。至於IOS有沒有這麼老實,我就不知道了。
Linux Check Memory Usage
所謂「惰性釋放內存」的說法,大概是把java虛擬機之類東西和傳統操作系統的相關概念搞混了——之後的唧唧歪歪無非是文過飾非乃至強辭奪理罷了;然而行內哪個詞能用在什麼地方是有共識的。
java有垃圾收集機制,內存不用時不用程序顯式刪除,忘記即可;垃圾收集系統會自動定期清理;這個清理時機常常是「內存不夠用時」,所以的確可以叫「惰性釋放」——內存其實早該釋放了,但既然還有空閑內存可用,那麼不釋放也沒什麼害處;不如攢一塊兒,等不清理不行時一下子清理乾淨算了。
但ios、linux/unix、windows壓根就沒提供「垃圾收集」機制,也沒有其它類似機制,自然也壓根談不上惰性不惰性了。
事實上,恰恰相反,unix系經典的「偷頁」演算法,反而是在內存未被佔滿之前,就把某些可能不再使用的內存頁提前放到交換區(即所謂的「虛擬內存」):這反而是在「積極釋放(物理)內存」了——不過,準確點說,這是「把暫時用不到的數據先存到磁碟空間」,從而使得「可用的物理內存」變多,並非「釋放內存」。
此外,一旦佔用內存的程序過多,就可能需要頻繁在內存和磁碟之間來回倒騰數據,此時系統就會陷入「顛簸」狀態。一旦進入這種狀態,機器就會變得非常非常慢,程序也非常容易崩潰——畢竟磁碟訪問速度比內存訪問速度要低上好幾個數量級。
————————————————————————
IOS/android等新興操作系統的確設計有一個特殊機制。這個機制允許程序切到後台時保存其運行現場信息;之後,如果長時間不使用該程序、或者內存緊張時,系統就可以把這樣的後台程序關閉,以便騰出更多內存空間。
當用戶再次激活此程序時,如果程序還在內存中,自然切回前台就可以立即執行;但如果程序已經被清出內存,那就需要重新載入、並讀取之前保存的運行現場信息,使程序恢復到之前狀態繼續運行——看起來就好像程序從未被關閉過一樣。
這個機制顯然並不適用於「(操作系統)什麼都不開時就佔用大量內存」的討論;它也不叫什麼「惰性釋放內存」,而是一個大得多的題目:「程序狀態持久化」。
只有狀態可持久化的程序才可以在暫時不用時,隨時由操作系統主動關閉,否則……等著用戶罵娘吧。
這種「事先做好準備、以便在內存不足時可安全的主動殺死後台進程獲取內存」的行為,顯然是非常非常「激進」的,因為它並不是「延緩本該釋放的內存釋放」,而是「主動幹掉不重要的進程,搶奪可用內存」——誰敢叫它「惰性「釋放內存?
————————————————————————
至於特定操作系統佔用的內存都做什麼用了……那可就太複雜了。
首先,系統提供的每個功能都需要一定的內存支持,功能多,內存佔用就多。換句話說,某些需求是硬性的,除非精簡功能,否則……
其次,就好像 @pansz 的答案中提到的,商家並沒有優化內存佔用的動機。畢竟程序員比內存可貴得多了——哪怕一個程序會影響數億部手機。
一個現成的例子就是java的垃圾回收機制:使用垃圾回收機制的程序,往往需要比手工管理內存的程序多好多倍的內存才能流暢運行(比如同樣的小遊戲,如果c/c++需要100M內存才能流暢運行的話,java很可能就得500M以上的內存才能有類似表現);但大家仍然寧可選擇java,因為內存實在太便宜了……
第三,因為現在有虛擬內存技術,可隨時把內存中暫時用不到的東西移到磁碟等大容量慢速存儲器上,緩解物理內存不足問題;這也導致商家沒有太大的動力去把內存佔用優化到極致:反正虛存管理演算法會自動解決問題。
更激進的,就是前面提到的「先讓程序支持運行狀態持久化、然後在必要時主動殺死進程釋放資源」這個做法,可用來緩解「系統中跑了太多進程,導致資源不足」問題。
既然這類問題可被各種技術自動緩解……那我們幹嘛還要付出大量時間、精力、金錢,冒著捅出大漏子的風險去優化它?
最後,可能是類似linux cache內存的「虛假佔用」:看似內存佔用很大,實則隨時可騰出來挪作他用:這些「無理佔用」的內存反而提高了系統的整體表現。
綜上,一句話:多佔點內存並不會立即導致明顯的嚴重後果;而且除非對內存的需求已經達到某個極限(比如導致「顛簸」),否則總有各種機制能夠自動緩解危機……而且,即便遇到了最壞情況,那麼最經濟的解決方案往往也是「換手機/升級硬體」而不是「做好優化」。
常年使用Windows的用戶經常會對內存管理機制有誤解。
首先,系統緩慢和卡頓並不是因為佔用的內存太多,恰恰是因為佔用不到內存。多數卡頓存在於內存和外存的數據交換上。所以在系統初始化的時候儘可能多的在內存中載入服務,反而會使app在調用的時候更加迅速。
加速系統的方法永遠不是釋放內存,而是提高內存的利用率。
第二,iOS優化的內存管理機制會使得活動量較少的程序儘早的退出內存,這樣可以為其他可能載入的程序提前開路。通俗的說,就是當系統判斷內存將要不夠的時候,自動幫你運行了內存清理。
第三,iOS還有一個內存管理特性,就是時間片輪轉。說白了就是,即使內存夠用,多數程序也不會長時間佔用內存。系統會給每個app進程裝一個計時器,當你退出程序home鍵那一刻,計時器就開始計時了,一旦數到十分鐘,系統自動幫你清理掉這個app。這也就是為什麼不能後台下電影的根本原因。
所以,用戶體驗至上就是這樣,你只是感到流暢了,卻不知道機智的程序員們在後面為了它做了多少優化。科技的牛逼之處,就是讓你感覺不到科技的存在。
總體說的比較通俗,各位大大輕噴。內存是幹什麼的?內存就是拿來用的啊!
不然空著給誰看?
類UNIX操作系統(包括Linux, Mac OS X, iOS, Android)的默認行為都是惰性釋放內存。
惰性釋放的意思是:能不釋放內存時就不要釋放內存,直到有新程序請求內存,而剩餘空間又不夠用的時候才釋放不用的內存。
假設系統有1GB內存,App A需要佔用300M,App B需要佔用400M, App C需要佔用500M。
當A和B正在運行時,系統內存被用去了700M。此時退出A,系統不釋放A佔用的300M內存,所以內存佔用依然是700M。此時A再次被啟動,系統可以不必從頭載入A了,只需要繼續用剛剛的300M內存就行,速度就快了。(而且對於iOS和Mac OS X而言,可以直接回到剛剛A剛剛離開的地方)。如果再退出B,此時系統依然佔用700M內存。這時運行C,系統發現剩餘的300M不夠用了,就把B原本佔用的400M給清理掉,於是C就能運行了。
為什麼不在程序退出的時候就清理掉內存呢?因為除了讓你數字上看起來舒服一點以外,這樣做沒有好處啊!程序數據在內存里,下次再啟動同一個程序就快得多,下次開另一個程序如果內存不夠,那現場清理就行了,清理內存速度很快,並不影響什麼。
這只是最簡單的比方。其實在iOS里,後台程序的規則要比這個複雜一些,不過,基本的思路就是這樣。所以內存佔用多沒什麼不好的。
================ 2015 年 8 月 14 日補充,不是專業用戶不必看了 ================
invalid s 的答案關於 Linux 內存管理的部分是正確的,Linux 的確實把剩餘內存用作了緩存,但緩存佔用的空間一樣是惰性釋放的。(廢話,不然還叫緩存么)(Java 虛擬機部分也是正確的,但是和我說的不是一回事。)我當年在寫這個答案時,沒打算寫給專業用戶看,就用一句惰性釋放內存帶過了,確實不嚴謹。事實上 iOS、Android 有自己的運行時環境,確實是像我上面說的這樣管理的。但是傳統操作系統比如 Linux 就要複雜一些。
「能不釋放內存時就不要釋放內存」 這條原則還是一樣,只是釋放的目標從整個 app 的內存在 Linux 中變成了 disk cache,而 disk cache 除了系統啟動時主動載入的一部分外,就是你之前用過的文件了。由於程序啟動時要載入一些文件,這些文件一旦被 cache 住,下次啟動速度就能加快不少。而系統去 cache 它的時機就是這些程序第一次啟動,從而第一次讀取那些必要文件時。
一個程序一般有 data, bss, heap, stack, code 幾個內存 section。在 Linux 中,程序退出時,bss, heap, stack 中的數據肯定是釋放了,因為下次再啟動程序這些 section 中的數據肯定不一樣,留著也沒什麼用。但由於 disk cache 的存在,code 和 data 中的只讀部分還在內存中。當進程再次啟動時,只要從內存中拷貝下這兩個 section 就可以了。基本思想還是一樣,就是把數據儘可能的留在內存中,以便將來再用時不用重新從磁碟讀取了。
上面只說了內存還非常夠用的情況,並不考慮 paging (或者說 swap, Windows 叫虛擬內存)。當內存接近不夠用,又有 swap 空間時,Linux 會稍微提早一點採取措施,如 invalid s 所說。但如果沒有 swap 的話,系統就只好釋放 disk cache 了。所以 Linux 里還是惰性釋放,只不過釋放的是 disk cache 而已。
近代 Windows 也是一樣的,只不過系統管理器里顯示給你內存時已經扣除了被 cache 的部分,讓你看著開心點。WIN7的內存:有CACHE機制,但CACHE部分顯示為可用內存。已用內存就僅僅是程序佔用的部分。
======================
我只是想說說WINDOWS的內存
先上傳一個我自己筆記本的內存佔用,WIN7,4G RAM(被集成顯卡吃了一口,屬性顯示3.86G可用)。
可以看到內存分成5個部分,分別是:
1、為硬體保留的內存:已保留供BIOS或其他外設的某些驅動程序使用的內存
2、正在使用:由進程、驅動程序或操作系統使用的內存
3、已修改:內容必須寫入磁碟才能用於其他用途的內存
4、備用:包含未活躍使用的緩存數據和代碼的內存
5、可用:不包含任何有價值數據,以及當進程、驅動程序或操作系統需要更多內存時將首先使用的內存
系統顯示的內存佔用部分就是第二部分,即真正正在使用的內存。別人說到的cache是第四部分,有內容,但統計時認為是可用內存。從數據上也可以看到,這張圖中的1355MB可用內存,正好等於第四、第五部分相加(1240+155)。這五部分相加正好等於4096MB,也就是我實際安裝的物理內存的數量。另外由於被集成顯卡吃了一口,變成3.86G可用,那麼被集成顯卡佔用的部分就是143.436MB,約等於第一部分的145MB。(我沒法真真正正的看到集成顯卡佔用的RAM數,因為我的筆記本是很奇葩的早期的T410,CPU自帶集成顯卡沒錯,但是被屏蔽了,又安了一個獨立顯卡NVS3100M,所以我現在電腦在邏輯上NVS3100單顯卡,但物理上是雙顯卡,只不過那個集成顯卡我永遠沒辦法用到,還白白吃了我一部分內存,估計還白白吃了我不少能耗……奇葩的聯想)
上圖是我用了某內存整理軟體之後的樣子……
第一部分沒變,第二部分大幅減少,但第三、第四部分大幅增加……但是系統自己顯示的時候是把第二部分當成已用,第四第五部分當成可用,所以……這麼整理之後看起來已用減少了,可用增加了,心裡很爽有沒有?但是不顯示的第三部分也增加了啊……第一張圖的已用是2564,可用是1355,加一起是3919,嗯,比4096沒少多少,勉強接受吧;但是特么的第二張圖是1244可用,1811可用,加起來是3055,居然少了那麼多……我的內存呢?哪去了??可是一般人只是看到佔用的變少了,可用的增加了,於是好爽……但實際上,這並沒有沒什麼卵用
最後,在我關閉內存整理軟體,然後寫完這個回復後,內存佔用慢慢變成了下面這個樣子。看起來內存整理軟體還沒準真的有點效果吧,起碼正在使用的部分真的減少了。另外WINDOWS的作法不錯,即儘可能的利用了內存,又照顧了強迫症們……
OS X的內存管理策略就是有多少就用多少,但不會OOM,系統調度會自動釋放內存,iOS是OS X的子集,所以同理,用戶根本不需要關心內存的問題。
如果你覺得慢,或者你發現打開某些App會失敗,或者出其他的問題,OK。那麼否則也許有問題。
否則,請相信我,Mac OS X/iOS的系統和系統工程師們比你更懂怎麼使用內存,交給他們好了。這是玩Android和Win留下的惡習。iOS與Android雖都基於UNIX,但運作機制不同不用我多解釋。Win與Android內存佔用高便是卡,可這不能用來看iOS。
論點:iOS的緩存比較激進,會把系統用到的binary儘可能加進內存,有類似OS X的機制。
實驗前提:
a. 兩台iOS7設備,低配版(4s)的功能基本沒有閹割,內存512;高配版內存1GB。 保證消耗內存能力差不多。
b. iOS無虛擬內存機制,測量純RAM消耗即可。
實驗現象:4s中的iOS吃掉了大約300MB的內存。題主表明5s吃內存為600MB。
結論:iOS對系統文件會大量緩存,對第三方app沒有此機制。
影響因素:
1. 64bit 5s vs 32bit 4s,歡迎持有iPhone 5的來評測一下。
2. 解析度差異,1136 vs 960
windows,android,佔用內存比600M更多。一個系統本身要符合大眾需求,隨著時間的推移,功能越做越多,預裝的模塊越來越多,預設內存佔用就會越來越高。
所以,除非安排程序員刻意的去優化內存佔用,否則內存佔用一定是高的。
其實這個問題,簡單的答案是:因為這不影響銷售。減小內存佔用是要花費額外的研發力量的,換句話說就是提升產品成本的,既然佔600M內存的用戶體驗已經足夠了,已經有人買買買,為什麼要花額外的努力去減小內存佔用呢?
要複雜了說呢?
例如,某些情況下程序員們不得不花額外的精力去節省內存。比方說下面的情況:
1:產品本身內存少(比如設備只有512M甚至256M內存),這樣我們不得不費心思節省內存,刪除一些東西。
2:老大說這個設備剩餘內存太少了,我們要優化用戶體驗。
5s佔600M應該已經是優化過的結果,不優化也許能佔到1G甚至更多。
從設備產商的角度,只有在明顯有必要投入精力去做優化的時候,才會進一步的去試圖減少內存佔用。否則就是「多一事不如少一事」
另外,系統內存佔用過多確實不是什麼好事,留給用戶應用的內存就變少了,各位為開機預設高內存佔用洗地的,我很感謝你們這麼為產商著想,但,這真的不是實情。如果真的有必要,做到200~300M佔用也可能,只是對5s這種機型確實沒必要而已。
若是對於512M內存配置的機型,一般是必須優化到400M佔用以下的,1G內存機型則沒必要折騰到這個程度,很多產商心目中認為留一半左右的可用ram就夠了。開機內存佔用少,需要花額外的研發精力,卻並不能提高產品賣點,只有少數的極客才會在意,那麼大多數產商自然並不會把重點放在這裡。
--
補充,有人說剩餘內存不用白不用,其實這是一個誤解。
os確實可以把剩餘內存全用作緩存,然而這部分內存是不被顯示為已經佔用的內存的,如果這部分內存也顯示為已佔用的內存,那麼你系統的內存佔用量將幾乎永遠約等於你的內存總量。內存佔用顯示就沒有了意義。
絕大多數內存查看軟體都不會把系統緩存顯示為已佔用的內存,換句話說系統剩餘的空閑內存才是真正的可以用作緩存的內存數量。
換句話說。剩餘內存越多,那麼系統可以用來自由當做緩存的內存就越多,性能應該就越好,這部分內存不會被顯示為已佔用,因而當你系統1G內存只顯示佔用了500M,另外500M可並沒有浪費,而是系統暗地裡分配給緩存了。我覺得比起某個傻逼公司設計的內存佔用到80%就要雙擊紅色的加速球,然並卵,最後卸載掉完全不卡要好多了
ios系統就算佔滿全部內存,你也不用擔心卡,跟android內存機制不太一樣。
ios的機制是最大可能的利用內存效率,但是同一時間只有一個app在占最大的資源
我的理解是這樣的。Windows是吃著碗里看著鍋里,餓了立馬去鍋里盛出來。 iOS是我都盛出來放在面前,都是我的,想起來吃,伸根筷子就好了。
「精裝房」當然到處擺滿傢具或裝飾,「毛坯房」才有充足的空間~
不佔用空著?
管他呢。反正又不卡
原先的程序在內存仍有佔用
你開新的程序的時候 系統會根據優先順序清理掉內存中部分無用的數據 把這部分空出來給新的程序用
而如果你開的還是之前開的程序 就直接拿內存中那一部分使用
但是並不卡
我內存滿了………
米4什麼不開佔1.5G,知足吧你!
推薦閱讀:
※鎚子 T1 和 iPhone 6 相比,有哪些先進的地方?
※蘋果的語音識別系統是誰做的?
※如何評價 iOS 11?
※蘋果公司做過哪些鮮為人知的努力?
※Apple 為 iOS 設備 Dock 默認應用所做的選擇是出於什麼理由? 比如 iPhone 是 Phone,Mail,Safari 及Music?
TAG:iPhone | 蘋果公司AppleInc | iOS開發 | 內存管理 |