天天看點

打破重重阻礙,手淘如何突破native crash提升穩定性?背景Native問題治理平台工具調研Native治理——Native Finder整體技術方案native crash治理過程展望

打破重重阻礙,手淘如何突破native crash提升穩定性?背景Native問題治理平台工具調研Native治理——Native Finder整體技術方案native crash治理過程展望

作者|潘文超(開風)

出品|阿裡巴巴新零售淘系技術部

導讀:本文是作者在 「Top100全球軟體案例研究峰會」上分享的——手淘Native治理,結合分享後的回報焦點,從 native 問題線下發現和快速定位、新so內建标準、線上曆史native問題治理等幾個方面為大家介紹,特産此文。

掃描下方二維碼,關注「淘系技術」微信公衆号,回複“native”即可擷取本次分享完整版 PPT 資料!

打破重重阻礙,手淘如何突破native crash提升穩定性?背景Native問題治理平台工具調研Native治理——Native Finder整體技術方案native crash治理過程展望

背景

打破重重阻礙,手淘如何突破native crash提升穩定性?背景Native問題治理平台工具調研Native治理——Native Finder整體技術方案native crash治理過程展望

無線用戶端 crash 一般分為 java crash 和 native crash ,無線應用往往為了追求更好的性能,把一些複雜的計算放到 native 層去實作,java 層通過 jni 調用 native 層實作,滿足功能場景;在 native 層産生的崩潰就産生了 native crash ;無線用戶端衡量穩定性的最重要的名額就是 crash 率,穩定性一直是各系統治理的重中之重,也是一直繞不開的話題,而 native 是目前業界認為治理最有難度,也是要重點突破的方向。接下來分析一下為什麼 native 治理值得去做以及如何做好。

▐ 目前手淘Android的crash現狀——找方向

從圖中我們可以看出,java crash 正常可以維持在較好的水準,手淘 native crash 一般比 java crash 要高,大促期間,由于手淘記憶體瓶頸, native crash 率會漲到日常水準的2-3倍。

從資料可見,native crash 是 java crash 的6倍之多,如果要想進一步突破,native 是有很大空間的,但 native 問題一般都很難定位, 堆棧不全,或者堆棧都集中在系統 so 上,無法直接定位問題,是以想要突破難度很大。手淘穩定性再上升一個台階,native crash是瓶頸,需要突破。

▐ native crash 治理挑戰——難

打破重重阻礙,手淘如何突破native crash提升穩定性?背景Native問題治理平台工具調研Native治理——Native Finder整體技術方案native crash治理過程展望

(1)難點一:crash堆棧目前絕大部分隻有系統so,缺乏問題關聯的業務子產品so,定位問題難度大,可以看一下如下的一個native crash堆棧,堆棧中的so都是系統的,無法直接定位業務問題。

(2)難點二:線上so都是去符号化的,即使堆棧中有業務so,也需要記錄該APP版本對應的符号化so做反解才能拿到能看得懂的堆棧。這點已經通過第一階段的native工程标準化解決,打出來的SDK包裡面必須要有對應的符号化so才可以內建。

(3)難點三:目前線下有效提前發現native問題的手段缺乏,想要提前發現,需要平台工具和有效手段。

▐ native crash 治理核心問題是什麼?——找抓手

要治理、要解決問題,首先得理清目前導緻 native crash 的問題,在做之前,做了一下 crash 資料分析,于是手動撈取了當時近5個版本的 top native crash 資料,占比最多的就是sig 6和sig 11。

那能說明什麼問題呢?signal 6這種崩潰信号要看具體場景,但根據具體資料分析,手淘裡面一般都是堆棧溢出、OOM 等導緻的。signal 11 這種崩潰基本就鎖定為記憶體問題了。

根據實際資料,大部分 crash 原因是因為記憶體,可以初步下的結論是,目前手淘 native crash 治理的關鍵是記憶體,解決手淘native記憶體相關的問題即可解決掉不部分問題。

Native問題治理平台工具調研

對集團内及業界的一些産品做了一些調研,詳細如下:

打破重重阻礙,手淘如何突破native crash提升穩定性?背景Native問題治理平台工具調研Native治理——Native Finder整體技術方案native crash治理過程展望

分别從使用成本、功能支撐、是否有堆棧能力,性能如何等次元進行了比較,其實我們的訴求是希望不需要 root 就能 run 起來,因為我們要持續內建、線上能灰階驗證,線下可以大規模任務執行、并且可以做手淘 native 問題沉澱,能把問題沉澱做成檢查項,可以涵蓋解決主要的記憶體問題,不止是記憶體洩漏。是以開發了Native Finder,希望能徹底治理好手淘 Native 問題。

Native治理——Native Finder整體技術方案

Native Finder是利用elf hook的原理,對malloc、free、realloc、alloc、mmap、munmap 等操作進行 hook,在自己的 hook 函數中,做一些智能分析和統計,并最後會調用系統記憶體操作函數,不破壞 so 原本發起的 malloc 等操作。

這個方案的缺點是會有一定的性能損耗,畢竟在 malloc 等操作中增加了一些分析和統計操作,但性能影響還好,在開了堆棧能力之後,APP性能會受影響,這個也是後面要優化的地方。整體技術方案如下:

打破重重阻礙,手淘如何突破native crash提升穩定性?背景Native問題治理平台工具調研Native治理——Native Finder整體技術方案native crash治理過程展望

native crash治理過程

打破重重阻礙,手淘如何突破native crash提升穩定性?背景Native問題治理平台工具調研Native治理——Native Finder整體技術方案native crash治理過程展望

首先在前期,花了比較多時間去研究曆史資料及問題,認真分析 crash 的關鍵問題和痛點是什麼,才找準了方向,分析出來記憶體問題是最痛的點。治理過程總結如上圖,分為5個階段。接一下講詳細介紹結合Native Finder工具平台的治理過程和心得。

▐ native工程标準化

治理總結如下:

打破重重阻礙,手淘如何突破native crash提升穩定性?背景Native問題治理平台工具調研Native治理——Native Finder整體技術方案native crash治理過程展望

總結起來這個階段我們做了3件事情:

第一,庫遷移,為什麼要做庫遷移呢?我們把老的gnu C++基礎庫遷移成libc++_ shared庫,所有so都做統一,歸一化,友善歸一native層問題;

第二,我們還做了重複so治理,因為不同so可能依賴了相同的so基礎庫,舉個例子,例如A so依賴了libopenSsl基礎so,B so也依賴了libopenSsl庫,但他們依賴的版本不同,這樣帶來的壞處是,首先會增加包大小,其次會有相同so的不同版本存在應用中,這給定位問題帶來了麻煩,是以需要對基礎so去重。

第三,每個版本包包括灰階版本都需要存儲下對應的符号化so,便于在crash發生後,我們對堆棧做符号化處理,這樣堆棧我們就能看懂了,加快和精準定位問題。這個階段是後面做的所有事情的基礎,非常重要。接下來我們看看下一個階段治理

▐ Native Finder開發完成,線下monkey跑native問題

打破重重阻礙,手淘如何突破native crash提升穩定性?背景Native問題治理平台工具調研Native治理——Native Finder整體技術方案native crash治理過程展望

此階段發現了幾個堆破壞的問題,但是經過好幾天反複線下執行 monkey,并未有任何進展。

後續調整思路,開始逐個分析線上存在的 native crash,并根據這些 crash 特征和根因開始沉澱經典問題,并把這些問題做成檢查項,跟同學交流和對焦後。

通過進一步的資料,發現記憶體 OOM 是目前優先級較高,且比較嚴重的問題,是以開始做這方面的技術建設,跟 crashSDK 打通,Native Finder 中統計和分析 so 次元占用記憶體未釋放的資料,在 crash 的時候做記憶體資訊 dump,并輸出輔助資訊,例如 malloc、mmap 次數、大記憶體(大于2M,屬于大記憶體申請,可配置,可動态調整)的申請等資訊。接下來看一下線下monkey 驅動階段

▐ 線上灰階,結合使用者真實操作場景crash

打破重重阻礙,手淘如何突破native crash提升穩定性?背景Native問題治理平台工具調研Native治理——Native Finder整體技術方案native crash治理過程展望

線下 monkey 并不能都能複現問題,借助工具平台拿到關鍵資訊去做問題解決和定位,我們希望場景更加豐富和多樣,是以我們把 Native Finder 放到線上,做了線上灰階。

随即把 Native Finder 放到線上做外灰,在使用者真實操作場景下的 crash,拿到 crash 時的記憶體 dump,但是經過一段時間的線上 crash 記憶體資訊采集,然後分析之後,沒發現明顯問題,從現在回頭看這個階段,其實當時的資料是能夠展現出問題的,隻是當時的想法不對。

▐ 虛拟記憶體不足,是目前OOM主要原因

我們對線上crash做了分析,同時也線上下做了可疑場景的嘗試複現,複現過程中,我們也做了大量資料的對比分析;

分析發現:正常 crash 跟 native oom crash,在記憶體詳細資料上做對比,發現OOM crash 在 native vmsize 上有較大差異,又看了很多手淘 OOM crash,發現都是這個原因,vmsize 暴漲。

大家都知道,32 位系統下,系統 vmszie 隻有4G,還要抛去一些系統核心占用、以及共享記憶體占用,vmsize比較有限,手淘又是一個體量很大的航空母艦,各個業務都想有最佳的業務體驗,都想用空間換時間,每個業務洩漏那麼一點,那手淘就被撐爆了,是累加洩漏的結果。

是以手淘 Android OOM 要一個一個解決,逐個挖出來,才能根治。我們整個過程沉澱了如下檢查項:一共沉澱了8項記憶體檢查,記憶體檢查項已經能覆寫 80% 以上的記憶體問題了;fd 檔案句柄檢查項一共沉澱了6項,fd 的檢查項已經能覆寫幾乎95%以上的 fd 問題了。

我們同時也研發了本地調試模式,友善開發和測試同學,能快速在本地複現和定位問題,具體的技術方案如下:

打破重重阻礙,手淘如何突破native crash提升穩定性?背景Native問題治理平台工具調研Native治理——Native Finder整體技術方案native crash治理過程展望

▐ 開始陸續發現各種 native 問題

朝着這個方向,對 Native Finder 做了逐漸優化,開始陸續發現各種問題,治理初步階段,我們通過 Native Finder 工具平台一共治理發現 20+ 問題,其中包括了多種問題類型,例如記憶體堆破壞、記憶體洩漏、OOM、記憶體操作越界、多次free、記憶體操作錯誤等。

同時手淘日常的 native crash 率也有明顯降低。到這裡,我們 native crash 已經初見成效。雖然通過治理,陸續發現了不少問題,但是還遠遠不夠,手淘記憶體問題依然嚴峻,特别是雙十一場景下,互動、活動以及各種場景鍊路互拉的場景,記憶體問題還是很嚴峻,後續還需更加努力。

展望

接下來我們希望還能做的更多,現在才剛剛開始;手淘記憶體問題依然嚴峻,要徹底治理,需要建立卡口,發現問題自動加入必改問題池,形成良性循環,舊問題不斷發現解決的同時,還需要杜絕新問題的引入。

除了 native so 導緻的記憶體問題,目前 H5 場景的記憶體問題也比較嚴峻,去手淘随便拿幾個 H5 頁面,看一下記憶體增量,都超過記憶體标準,H5缺乏管控,下半年需要對H5記憶體做卡口嚴控;目前針對前端的記憶體洩漏,還沒有有效的手段去檢測發現,從native層看,都展現在核心上,核心應該是沒有問題的,如果有效發現前端代碼導緻的記憶體洩漏,也是一個值得研究的點,不過先做卡口再做進一步突破。

打破重重阻礙,手淘如何突破native crash提升穩定性?背景Native問題治理平台工具調研Native治理——Native Finder整體技術方案native crash治理過程展望

今日吐槽

大家都在 native 治理上遇到哪些坑?

歡迎評論區留言,和小橙子分享哦~

We are hiring

淘系技術品質團隊負責保障整個淘寶和天貓主站的業務品質,在這裡有豐富多樣的業務場景和技術挑戰,以及很多優秀的合作夥伴。在這裡你不僅能夠了解世界級雙十一是如何保障的,最關鍵的是有對技術極緻追求,對生活的充滿熱愛的一群俊男美女們。

還等什麼,趕緊加入我們一起共同打造淘系的技術品質。

請投遞履歷至郵箱:[email protected]

關注【淘系技術】,一個有内容,有溫度的微信公衆号!

打破重重阻礙,手淘如何突破native crash提升穩定性?背景Native問題治理平台工具調研Native治理——Native Finder整體技術方案native crash治理過程展望