1. 程式人生 > >【騰訊開源】iOS爆記憶體問題解決方案-OOMDetector元件

【騰訊開源】iOS爆記憶體問題解決方案-OOMDetector元件

元件介紹

OOMDetector是手Q自研的IOS記憶體監控元件,騰訊內部目前已有多個App接入了OOMDetector,它主要有以下兩個功能:

  • 爆記憶體堆疊統計:負責記錄程序記憶體分配堆疊和記憶體塊大小,在爆記憶體時Dump堆疊資料到磁碟

  • 記憶體洩漏檢測:檢測記憶體洩漏,目前支援Malloc記憶體塊和OC物件的洩漏檢測

OOMDetector可以快速幫助開發者發現和定位App爆記憶體問題和記憶體洩漏,元件目前已經在Github開源,原始碼地址:https://github.com/Tencent/OOMDetector

背景

目前業內已有一些比較的IOS記憶體分析工具,下面逐個介紹這些工具的功能以及它們在使用上的不足。

Allocation

作為IOS開發,我們都很熟悉蘋果官方提供的Allocation記憶體分析工具,在開發除錯階段,可以用Allocation詳細分析App各模組記憶體佔用。Allocation對App的記憶體監控比較全面,能監控到所有堆記憶體以及部分VM記憶體分配。雖然Allocation的功能比較強大,但是它也有比較明顯的使用侷限性,主要表現為以下兩點:

  • 無法獨立在App執行,只能在除錯階段連線Mac使用

  • 效能較差,大型App開啟後容易引發卡死

這兩點限制決定了Allocation只適合於在開發階段輔助分析程式碼中存在的記憶體問題,而無法直接對線上使用者的問題進行監控和定位。

FBAllocationTracker

FBAllocationTracker是Facebook開源的記憶體分析工具,它的原理是用 Method Swizzling替換原本的alloc方法,這樣可以在App執行時記錄所有OC例項的分配資訊,幫助App在執行階段發現一些OC物件的異常增長問題。相比Allocation,FBAllocationTracker對App效能影響較低,可以在App中獨立執行。但是這個工具也有比較明顯的缺陷:

  • 監控範圍不夠全面,只能監控OC物件,不能監控C++物件和malloc記憶體塊以及VM記憶體

  • 沒有記憶體物件分配的堆疊資訊,對於開發者來說很難只通過物件的型別和數量定位到記憶體增長的原因

綜上所述,FBAllocationTracker雖然能獨立在App中執行,但是監控的記憶體範圍太小,同時記錄的物件資訊也過於簡單,對於分析記憶體問題幫助十分有限。

記憶體問題一直是手Q的關注重點,為了保證線上大盤使用者的記憶體質量,我們希望有一款工具能夠幫助監控和定位線上使用者的記憶體問題。基於這樣的背景,我們團隊自研了OOMDetector元件。OOMDetector通過Hook系統底層的記憶體分配方法,能夠記錄到程序所有記憶體分配的堆疊資訊,同時元件能夠在對效能流暢度影響不大的情況下能夠保證在App中獨立執行,可以方便用於分析和監控線上使用者的記憶體問題(爆記憶體或者記憶體洩漏問題)。

元件原理

爆記憶體堆疊統計

爆記憶體堆疊監控原理

爆記憶體堆疊監控的實現原理如圖1所示,通過Hook IOS系統底層記憶體分配的相關方法(包括malloc_zone相關的堆記憶體分配以及vm_allocate對應的VM記憶體分配方法),跟蹤並記錄程序中每個物件記憶體的分配資訊,包括分配堆疊、累計分配次數、累計分配記憶體等,這些資訊也會被快取到程序記憶體中。在記憶體觸頂的時候,元件會定時Dump這些堆疊資訊到本地磁碟,這樣如果程式爆記憶體了,就可以將爆記憶體前Dump的堆疊資料上報到後臺伺服器進行分析。

圖1 爆記憶體監控原理

效能挑戰

App的記憶體分配方法的呼叫頻率非常高,在大型App中可能高達10W/次每秒。要Hook這類方法對元件的效能來說是極大的挑戰,因為如果元件本身耗時的話就很容易導致App卡頓甚至卡死。在OOMDetector中,我們對Hook方法程式碼的執行效率進行了嚴格控制,也採取了一些策略對Hook方法中耗時較多的堆疊回溯和鎖等待進行了優化:

  • 優化堆疊回溯方法

對於堆疊回溯,系統提供了backtrace_symbols方法可以直接獲取堆疊資訊,但是這個方法特別耗時。所以我們根據堆疊的回溯原理實現了更高效的堆疊回溯方法,優化後的方法在執行時只會獲取堆疊函式的地址資訊,在回寫磁碟的時候再根據動態庫的地址範圍拼裝成如圖2所示堆疊格式(類似Crash堆疊),後臺伺服器利用atos命令和符號表檔案就可以還原出對應的堆疊內容。通過這種方式可以把耗時較高的符號還原工作放到伺服器端,客戶端只需要執行耗時較少的堆疊函式地址回溯操作,優化後的堆疊回溯方法耗時低於1us。

圖2 堆疊格式

  • 優化鎖等待耗時

對於多執行緒的記憶體分配,為了保證執行緒安全,堆疊資料的插入操作必須要上鎖。對於這種高頻呼叫的方法,鎖的效能是我們最關心的指標。IOS開發中NSLock和@synchronized是比較常用的,那麼這兩種鎖的效能如何呢?

我們通過測試程式碼對IOS中常用的鎖進行了測試,總結了圖2所示的各種鎖的效能比較圖,根據圖3的測試結果,NSLock和@synchronized的效能要低於pthread_mutex,效能最好的是自旋鎖OSSpinLock。

自旋鎖的原理是,如果自旋鎖已經被別的執行單元保持,呼叫者就一直迴圈等待鎖的釋放。相比互斥鎖而言,自旋鎖不會引起呼叫者休眠,節省了執行緒休眠的狀態切換,所以有更高的效率,但代價是增加了cpu的使用率。對於我們的場景,因為需要上鎖部分的程式碼執行耗時較少,採用OSSpinLock的自旋鎖並不會顯著增加cpu的使用率,所以我們優先考慮鎖的效率採用了OSSpinLock的方案。

圖3 各種鎖的效能比較

堆疊聚類和壓縮

之前提到,我們的Hook方法會快取每個記憶體分配的堆疊資料。假設App的記憶體塊個數為25W,堆疊平均深度20行,每個堆疊地址採用8位元組的整型資料儲存,那麼25W個堆疊資料將佔用40M的記憶體空間。顯然這樣的記憶體增長對於任何App都是不可承受的,所以我們需要對元件的記憶體佔用進行優化。

我們分析爆記憶體問題時候,只需要分析那些記憶體佔用較大的堆疊,基本不用關心那些記憶體佔用較小的堆疊。所以我們的優化思路也很明確:只保留記憶體佔用較大的堆疊。要完成這個工作就必須對記憶體中所有堆疊先進行聚類合併,統計出每個堆疊累計的記憶體值。

具體的優化策略如圖4所示,對於每個記錄到的分配堆疊,首先通過md5演算法將堆疊資料壓縮為16位元組的md5,通過md5值進行聚類,快取中只保留16位元組的md5資料,只有當某個堆疊的累計記憶體超過一定閥值時,才會保留原始堆疊資訊,這樣因為超過閥值的堆疊數量有限,堆疊原始資訊佔用的空間幾乎就可以忽略不計了。

圖4 堆疊聚類和壓縮原理

採用兩種方式可以將堆疊降低到優化前的1/40左右,優化後的元件記憶體基本不會對App的記憶體造成太大影響。

資料Dump方案

前面提到,在記憶體觸頂後要將記憶體中的堆疊資料定時Dump到磁碟中,常規的方案是IO介面直接把資料寫入到磁碟。因為資料Dump的頻率較高,頻繁的IO操作會導致程式卡頓。因為資料Dump的操作是非常高頻的,所以我們採用了效率更高的mmap方式。

mmap是一種記憶體對映檔案的方法,即將一個檔案或者其它物件對映到程序的地址空間。實現這樣的直接對映關係後,寫檔案的過程程序不會有額外的檔案的資料拷貝操作,避免了核心空間和使用者空間的頻繁切換,如圖5所示。根據我們的程式碼實測,向mmap對映空間寫資料的效能與直接寫記憶體一致,效率遠高於IO操作。

圖5 記憶體對映原理

那麼mmap的回寫時機是怎樣的?根據官方文件描述,主要有如下時機:

  • 系統記憶體不足時

  • 程序crash時

  • 主動呼叫 msync時

mmap 在記憶體不足時會主動進行回寫操作,這樣的機制也保證我們的監控元件能在程式爆記憶體前將快取中的資料回寫到磁碟,從這一點看採用mmap的方式相比常規IO操作也有更強可靠性。

記憶體洩漏檢測

除了爆記憶體堆疊監控,OOMDetector還集成了記憶體洩漏檢測功能,能夠檢測Malloc記憶體塊和OC物件的“無主記憶體洩漏”。所謂“無主記憶體洩漏”是指記憶體塊在程序內已經沒有引用卻無法正常釋放的記憶體塊。

按照之前介紹的方案,OOMDetector可以記錄到每一個物件的分配堆疊資訊,要從這些物件中找出 “洩漏物件”,我們需要知道在程式可訪問的程序記憶體空間中,是否有“指標變數”指向對應的記憶體塊,那些在整個程序記憶體空間都沒有指標指向的記憶體塊,就是我們要找的洩漏記憶體塊。如圖2所示,在IOS系統中,可能包含指標變數的記憶體區域有堆記憶體、棧記憶體、全域性資料區和暫存器,OOMDetector 通過對這些區域遍歷掃描即可找到所有可能的“指標變數”,整個掃描流程結束後都沒有“指標變數”指向的記憶體塊即是洩漏記憶體塊。

為了避免記憶體訪問衝突,掃描過程需要掛起所有執行緒,整個過程會卡住程式1-2秒。因為掃描過程較為耗時,這個功能目前主要用於App的測試階段,與自動化測試結合可快速高效的發現洩漏問題。

圖6 記憶體洩漏檢測原理

展望

開源只是開始,我們後續仍會不斷對OOMDetector元件進行改進,也歡迎大家對元件多提意見。如果你的IOS應用也在受到記憶體問題困擾或者你也對IOS記憶體監控技術感興趣,那麼來了解下我們的元件吧!

相關推薦

開源iOS記憶體問題解決方案-OOMDetector元件

元件介紹 OOMDetector是手Q自研的IOS記憶體監控元件,騰訊內部目前已有多個App接入了OOMDetector,它主要有以下兩個功能: 爆記憶體堆疊統計:負責記錄程序記憶體分配堆疊和記憶體塊大小,在爆記憶體時Dump堆疊資料到磁碟 記憶體洩漏檢測

開源LivePool:基於Node.js的跨平臺Web抓包替換工具

LivePool 是一個基於 NodeJS,類似 Fiddler 能夠支援抓包和本地替換的 Web 開發除錯工具,是Tencent AlloyTeam 在開發實踐過程總結出的一套的便捷的工作流以及除錯方案。 背景 在 Windows 平臺上,Fiddler 作為一款非常便捷好用的 Web 除錯工具

CVM的功能和優勢學習總結

騰訊雲 騰訊雲的功能 騰訊雲的特點 騰訊雲的功能與優勢具有以下幾個方面:提供全面的服務彈性的雲端CVM的管理平臺可靠CVM極速的CVM性能多種解決方案來保證CVM和數據的安全簡單易用多種計費模式,降低IT投入成本騰訊雲CVM提供了全方面的服務內容,具體為以下幾類:實現了多region多zone覆蓋

自己搭建的雲伺服器JavaEE環境

轉載地址:https://www.cnblogs.com/qlqwjy/p/8727487.html 感覺很專業的樣子,還沒有看完,更沒有實踐,找個機會實踐一下。 0.安裝SSH登入 1.生成公鑰對 ssh-keygen -t rsa -P ''   -P表示密

TMQ這樣的測試過程管理讓你事半功倍

導語 相信每一位測試小夥伴對於測試過程管理都有自己的獨特見解。我所在的部門2017年初開始施行測試變革——“測試左移”。過程中有從技術層面的”左移“,也有從流程層面的”左移“等等,方式形態萬千。今天和大家分享的是我在這個過程中,除了個人技術能力提升外,在測試過

TMQ從0開始做後臺測試

從使用者反饋說起 “我備份的照片怎麼不見了”; “出現伺服器錯誤-1001”; “下載的照片無法顯示”。 使用者反饋,測試過程中經常遇到各種與後臺相關的非必現問題,對於一個重後臺功能的產品,包括很多業務邏輯和使用者的資料都與後臺強相關,若只是通過客戶端來

TMQ如何輕鬆爬取網頁資料

一、引言 在實際工作中,難免會遇到從網頁爬取資料資訊的需求,如:從微軟官網上爬取最新發布的系統版本。很明顯這是個網頁爬蟲的工作,所謂網頁爬蟲,就是需要模擬瀏覽器,向網路伺服器傳送請求以便將網路資源從網路流中讀取出來,儲存到本地,並對這些資訊做些簡單提取,將我們

TMQ測試左移專欄用Powermock和Mockito來做安卓單元測試

作者:ZeusL 團隊:騰訊移動品質中心TMQ 一、單元測試及Android單元測試簡介 慣例,先簡單介紹下理論知識,懂得的可以跳過。 1、單元測試定義和特性 單測定義: 在計算機程式設計中,單元測試(Unit Testing)又稱為模組測試,

TMQ再不建模你就out了

導語 加入測試建模小組八個多月的時間,在日常的測試工作中,經常會有身邊的小夥伴們對我們的建模很好奇,會問“什麼是測試建模?”“為什麼要測試建模?”“建模能給我們帶來什麼好處?”“建模和我們現在的測試設計區別到底在哪裡?“等等諸如此類的問題。思來想去,實在有必要

TMQGoogle是如何做Chrome瀏覽器的效能測試的?

導語 近期研究了一下chrome的強大的效能測試工具telemetry,收穫頗豐,現簡單介紹一下telemetry的測試框架。telemetry中的很多方法都正在逐步的引入到自研的桌面QQ瀏覽器效能自動化測試系統中。 一、概述 Telemetry是一套

TMQ遠端移動測試平臺對比分析

作者:趙麗娜 隨著移動裝置和系統的碎片化程度越來越高以及複雜的行動網路情況, 相容性測試以及遠端真機測試的重要性越來越突出。根據遠端測試機/人員與開發者間的合作方式,可以分為以下幾種服務:雲測試服務、內測服務以及眾測服務,相應的平臺支援如下圖。 雲

TMQUTP自動化測試平臺系列之三用例管理

導語 UTP自動化測試平臺是TMQ的一個聯合專案,目的是方便各專案測試人員更好地開展自動化測試建設工作,減少重複平臺建設的成本,提高產品的自動化測試效率。 背景 測試用例,是測試的基礎原料,沒有用例,測試工作無法執行,自動化測試也是一樣。實際的自動化測

TMQJAVA程式碼覆蓋率工具JaCoCo-踩坑篇

作者:劉洋 一、覆蓋率踩過的坑 在專案中使用JaCoCo覆蓋率的時候,也遇到過各種奇葩的問題,在這裡列出來分享下,問題和實際的專案關係密切,希望對有遇到過相似問題的童鞋有所啟發。 1.1 覆蓋率包在部分手機6.0上安裝失敗 事情起因:在測試新功

TMQTTS評測--方案介紹和實踐分享

導讀 語音合成(Text To Speech,TTS)技術將文字轉化為聲音,目前廣泛應用於語音助手、智慧音箱、地圖導航等場景。TTS的實現涉及到語言學、語音學的諸多複雜知識,因合成技術的區別,不同的TTS系統在準確性、自然度、清晰度、還原度等方面也有著不一樣的

地圖出現“鑑權失敗,請傳入正確的key”怎麼解決

騰訊地圖使用中,出現了“鑑權失敗,請傳入正確的key”,需要到騰訊官方申請一個key. 如圖所示,複製KEY過來,找到報錯頁面,加上 <script charset="utf-8" src="h

TMQ測試管理平臺大比拼

作者:solinazhao 簡介 測試管理平臺是貫穿測試整個生命週期的工具集合,它主要解決的是測試過程中團隊協作的問題,比如缺陷管理、用例管理、測試任務管理等。 目前市面上比較流行的測試管理工具有QC、 Mantis、 BugZilla、TestL

人工智能AI:車牌識別停車場管理系統

運行 基於 臨時 所有 sig idt 51cto lis amp 車牌OCR接口 接口描述根據用戶上傳的車牌圖像,返回識別出的車牌字段信息。 請求參數參數名稱 是否必選 數據類型 數據約束 示例數據 描述app_id 是 int

sql server 20081433埠開啟解決方案

檢視電腦開放埠命令為:netstat -an SQL Server 2008一般預設的埠為 1433 ,但有時會遇到無法連線埠1433的問題,檢查埠1433是否啟用的方法為: 開始–>輸入cmd –>回車–>telnet localhost 1433->回車 出現黑屏,表示本機連線埠1

安卓-自定義佈局安卓App開發思路 一步一個腳印(十)實現內嵌在app中的webview 開源X5 高效安全

實現內嵌在app中的webview 採用騰訊開源X5 高效安全 webview在app的使用中,十分頻繁,原生的webview載入速度相對來說很慢,而且很費流量。騰訊開源了x5的webview

Bugly乾貨分享iOS黑客技術大揭祕

“8小時內拼工作,8小時外拼成長”這是大家共同的理想。除了每天忙於工作外,我們都希望能更多地區吸收領域內的新知識與新技能,從而走向人生巔峰。 Dev Club 是一個交流移動開發技術,結交朋友,擴充套件人脈的社群,成員都是經過稽核的移動開發工程師。每週都會