精品国产一级在线观看,国产成人综合久久精品亚洲,免费一级欧美大片在线观看

Facebook如何降低應用中的FOOMs

責任編輯:editor005

2015-11-09 13:52:15

摘自:Facebook的博客

我們試圖做過大量的優化,例如清理緩存和內容,但是應用進程的內存占用在跳轉向 web 視圖時總是顯著增長。然后我們用新實現的增加和減少的分配和釋放實例數量的方法相應地替代+alloc 和 +dealloc。

在 Facebook,我們一直致力于讓應用穩定、快速、可靠。在 Facebook 的 iOS 應用上,我們已經做了很多工作去減少應用的崩潰率以及全面提高應用的穩定性。此前,大多數的崩潰都是由于常規性錯誤,一般都會伴隨著相應代碼行的棧回溯信息,并且提供了可能導致問題所在的提示信息。

當我們繼續解決崩潰問題時,我們觀察到需要解決的崩潰比例正在下降,但是我們注意到 App Store 指出社區繼續出現令人失望的應用崩潰。我們深入研究了用戶報告,并且從理論上說明內存不足(out-of-memory events (OOMs))可能正在發生。OOMs 一般發生在系統運行在低內存的環境下,OS 為了回收內存而終止應用。它既可能發生在前臺,也可以是后臺。我們在內部稱之為 FOOMs 和 BOOMs — 當我們說應用爆炸(BOOM)了,好像很好玩的樣子。

從用戶的角度來看,一個前臺內存不足導致的崩潰和常規的崩潰是不好分辨的。一般分為幾種情況,應用異常終止,似乎消失,以及用戶返回設備主屏幕。如果內存的消耗速度急速增長,那么應用會在不接到任何通知的情況下被終止掉。在 iOS 中,OS 會將內存警告發給應用,但是不能保證 OS 一定會在終止應用之前給應用發送警告信息。這就導致我們無法輕易地知道應用是否是由于內存壓力而被 OS 終止。

  分析問題

為了掌握應用由于 OOM 崩潰而終止的頻率,我們從所有已知的途徑列舉應用可能終止的情況并記錄他們。這樣問題就轉變為“導致應用重啟的是什么?”

應用需要重啟的原因如下:

應用已經更新

應用退出或終止

應用崩潰

用戶強制退出應用

設備重啟(包括 OS 升級)

應用在前臺或者后臺內存不足(OOM)

通過排除處理,尋找區別于其他重啟原因的實例,借此我們可以找出 OOM 發生的時間。此外,我們還追蹤應用進入后臺和前臺的時間,借此我們可以精確地把 OOMs 分為 BOOMs 和 FOOMs。

日志顯示在設備處于低內存狀態下,OOMs發生的比率很高 。當應用進程在受內存限制的設備上像驅逐一樣被終止,真的非常令人沮喪。查看相關的日志記錄幫助我們驗證排除法的效果,并且能繼續提高日志記錄(我們無法準確驗證所有的事例,例如應用升級)。

我們最初在減少 OOMs 所做的努力,是試圖在應用不再需要內存時,就盡可能快地主動縮小應用的內存占用。不幸的是,我們沒有發現 OOM 崩潰的數量沒有有切實的改變,所以我們把關注點轉移到大的內存分配上,開始觀察那些可能被泄露的內存(沒有清理干凈的),尤其是潛在的循環引用。

內存使用分析

當我們開始解決內存泄露問題時,我們看到 OOM 崩潰率有所降低,但是依然沒有達到我們預期。緊接著,我們深入研究 Apple 的 Instruments 應用的 memory profiler,并且注意到只要應用打開任何 web 網頁,一個重復樣式的 UIWebView 就會分配大量的內存。我們還發現內存經常沒有回收,即使在用戶離開了網頁并且 web 視圖被關閉的情況下。

我們試圖做過大量的優化,例如清理緩存和內容,但是應用進程的內存占用在跳轉向 web 視圖時總是顯著增長。iOS包含一個新的類 — WKWebView — 它把大多數的工作都放在了分開的進程里,這意味著大多數跟內存相關的 web 視圖使用將不會分配給我們的進程。在低內存的事件中,web 視圖的進程將會被終止,但是我們的應用有很大可能會繼續存活下去。在我們把應用遷移為 WKWebView 后,我們確切地看到 OOMs 發生的比率有了顯著的降低。Yay!

  內存分配比率

當通過 Instruments 分析內存使用時,我們還發現應用中分配了大量的臨時內存(~30 MB),然后馬上釋放掉。如果 CPU 在這個分配過程中是空閑的,那么 OS 會終止程序。我們要禁止此類臨時分配,這可以幫助我們在 30% 確定場景中減少 OOM 崩潰,我們還實驗并發現,相較于重復分配和釋放內存,分配一次然后管理內存對于應用的可靠性是更好的。

阻止內存惡化

即使用了 WKWebView,我們仍然發現一點點內存泄露都能夠顯著地導致影響 OOM 的發生比率。在我們通常的發布計劃和貢獻給應用的許多的團隊中,在發布的應用中捕獲和阻止內存泄露是非常重要的。我們改變了掃描設備,獨創性地設計了用于測試移動性能,為了記錄大量進程中的常駐內存,允許掃描設備去標記惡化情況,只要它們被添加了。這已經幫助我們把 OOM 發生比率保持在比最初解決問題時低得多的水平上。

應用內部的內存分析器

上一個在這個項目中我們使用的關鍵技術是去構造一個應用內部的內存分析器,通過追蹤所有的 Objective-C 對象的內存分配進而快速分析應用。我們把這個配置在掃描儀上,然后在里面建立我們的應用。

它是如何工作的:對于系統中的每一個類,維護一個當前活動的實例的數量。我們可以在任何點要求它打印出每一個類對象的現存數目。然后我們就可以分析這些數據任何異常的 release-to-release 用以辨認我們應用中總體上的內存分配模式,如果計數急劇變化,這一般可以驗證為內存泄露。我們準備去用一種性能足夠用并且不會產生對用戶有影響的方法去實現。

下面簡要說明我們的策略以及我們是如何追蹤 NSObject 的內存分配。

我們一開始創建一個內存分配追蹤類。這是個超級直接和簡單的類,有統計實例數量的公共方法用于統計實例數量的增加和減少。我們使用 C++ 而不是Objective-C,是由于那樣可以最小化追蹤器的內存分配和 CPU 占有率。

class AllocationTracker { static AllocationTracker* tracker(); void incrementInstanceCountForClass(Class aCls); void decrementInstanceCountForClass(Class aCls); std::vector countsSnapshot(); ... }

然后我們可以使用 iOS 的方法調配技術(稱為“swizzling”,使用runtime 的class_replaceMethod方法),用-fb_originalAlloc 和 -fb_originalDealloc方法去替換標準的iOS方法 +alloc 和+dealloc。

然后我們用新實現的增加和減少的分配和釋放實例數量的方法相應地替代+alloc 和 +dealloc。

@implementation NSObject (AllocationTracker) + (id)fb_newAlloc id object = [self fb_originalAlloc]; AllocationTracker::tracker()->incrementInstanceCountForClass([object class]); return object; - (void)fb_newDealloc AllocationTracker::tracker()->decrementInstanceCountForClass([object class]); [self fb_originalDealloc]; @end

然后,當應用運行時,我們可以調用快照方法有規律地打印當前存活實例的數量。

應用可靠性

一旦我們在 Facebook 的 iOS 應用中實施更改去解決內存問題,我們會看到 (F)OOMs 和用戶的應用崩潰報告有顯著的降低。OOM 崩潰對于我們來說是盲點,因為沒有正式的體系或者 API 可以隨意檢測到它們。沒有人喜歡一個應用突然關閉。但是使用某些工具,或者最新的 iOS 技術,以及一些靈巧的方法去解決這個問題,能夠讓我們的應用更加可靠,并且保證你不會在打開 web 視圖查看一篇有趣的文章(就像你在看的這篇文章)時突然關閉。

Additional thanks to Linji Yang, Anoop Chaurasiya, Flynn Heiss, Parthiv Patel, Justin Pasqualini, Cloud Xu, Gautham Badrinathan, Ari Grant, and many others for helping reduce the FOOM rate.

鏈接已復制,快去分享吧

企業網版權所有?2010-2024 京ICP備09108050號-6京公網安備 11010502049343號

  • <menuitem id="jw4sk"></menuitem>

    1. <form id="jw4sk"><tbody id="jw4sk"><dfn id="jw4sk"></dfn></tbody></form>
      主站蜘蛛池模板: 左贡县| 海门市| 清远市| 丰原市| 大荔县| 奉贤区| 罗江县| 昭觉县| 平定县| 育儿| 绍兴县| 鹤岗市| 延安市| 高陵县| 成武县| 行唐县| 三台县| 江达县| 北宁市| 上蔡县| 沙田区| 崇文区| 苏尼特左旗| 卢湾区| 青川县| 西安市| 镇安县| 黎城县| 甘德县| 惠东县| 赣榆县| 健康| 岳池县| 哈尔滨市| 通州区| 阳谷县| 洛宁县| 封开县| 湘阴县| 金寨县| 清远市|