iOS Abort问题系统性解决方案
一、背景
崩潰(Crash),即閃退,多指移動(dòng)設(shè)備(如iOS、Android設(shè)備)在打開(kāi)/使用應(yīng)用程序的過(guò)程中,突然出現(xiàn)意外退出/中斷的情況。如果App線上版本頻繁發(fā)生崩潰,會(huì)極大地影響用戶體驗(yàn),甚至導(dǎo)致用戶流失,以及收益減少。因此,崩潰問(wèn)題是客戶端穩(wěn)定性團(tuán)隊(duì)需要重點(diǎn)解決的問(wèn)題。
然而,對(duì)于所有崩潰場(chǎng)景,僅25%的崩潰可通過(guò)信號(hào)量捕獲,實(shí)施相應(yīng)改進(jìn);另有75%的崩潰則難以識(shí)別,從而對(duì)App的用戶體驗(yàn),造成了巨大的潛在影響。
Facebook的工程師將App退出分為以下6個(gè)類(lèi)別:
1.App內(nèi)部主動(dòng)調(diào)用exit()或abort()退出;
2.App升級(jí)過(guò)程中,用戶進(jìn)程被殺死;
3.系統(tǒng)升級(jí)過(guò)程中,用戶進(jìn)程被殺死;
4.App在后臺(tái)被殺死;
5.App在前臺(tái)被殺死,且可獲取堆棧;
6.App在前臺(tái)被殺死,且無(wú)法獲取堆棧。
對(duì)于第1~4類(lèi)退出,屬于App的正常退出,對(duì)用戶體驗(yàn)沒(méi)有太大影響,無(wú)需進(jìn)行相應(yīng)處理;對(duì)于第5類(lèi)退出,可通過(guò)堆棧代碼級(jí)定位崩潰原因,對(duì)此業(yè)界已形成比較成熟的解決方案,推薦免費(fèi)試用阿里云的崩潰分析服務(wù),即可快速定位、解決此類(lèi)崩潰問(wèn)題;對(duì)于第6類(lèi)退出,可能的原因很多,包括但不限于:系統(tǒng)內(nèi)存不足時(shí)繼續(xù)申請(qǐng)內(nèi)存、主線程卡死20s以上、CPU使用率過(guò)高Stack Overflow等,在此我們統(tǒng)一稱(chēng)之為iOS客戶端的“Abort問(wèn)題”。
Abort問(wèn)題無(wú)法被堆棧捕獲,且發(fā)生頻次遠(yuǎn)高于可被捕獲的崩潰(下稱(chēng)“堆棧崩潰”)。從歷史數(shù)據(jù)來(lái)看,手淘(電商類(lèi)超級(jí)App代表)的Abort問(wèn)題數(shù)量一般是堆棧崩潰數(shù)量的3倍左右;優(yōu)酷Pad(視頻類(lèi)超級(jí)App代表)的Abort問(wèn)題數(shù)量一般是堆棧崩潰數(shù)量的5倍左右??梢?jiàn),Abort問(wèn)題對(duì)用戶的使用體驗(yàn)造成巨大影響。
本文將針對(duì)iOS客戶端的Abort問(wèn)題,進(jìn)行根因定位分析,并提出系統(tǒng)性解決方案。
二、Abort問(wèn)題的原因分類(lèi)
形成Abort問(wèn)題的原因主要包括以下4個(gè)。
2.1 內(nèi)存Jetsam
移動(dòng)端設(shè)備的物理內(nèi)存資源緊張,但App仍不斷申請(qǐng)內(nèi)存。因此系統(tǒng)signal 9殺死進(jìn)程,造成異常退出。
{ "memoryPages" : { "active" : 24493, "throttled" : 0, "fileBacked" : 24113, "wired" : 13007, "anonymous" : 12915, "purgeable" : 127, "inactive" : 10955, "free" : 2290, "speculative" : 1580 }, "uncompressed" : 125795, "decompressions" : 143684 }, "largestProcess" : "Taobao4iPhone", "processes" : [ { ... { "rpages" : 2050, "states" : [ "frontmost", "resume" ], "name" : "Taobao4iPhone", "pid" : 1518, "reason" : "vm-thrashing", "fds" : 50, "uuid" : "5103a88a-917f-319e-8553-c0189dd1abac", "purgeable" : 127, "cpuTime" : 4.619693, "lifetimeMax" : 3557 }, ... }2.2 主線程死鎖
A/B兩個(gè)線程同時(shí)等待對(duì)方完成某些操作,因而無(wú)法繼續(xù)執(zhí)行,形成死鎖,造成異常退出。
Exception Type: 00000020 Exception Codes: 0x000000008badf00d Highlighted Thread: 0Application Specific Information: com.myapp.myapp failed to scene-create in timeElapsed total CPU time (seconds): 4.230 (user 4.230, system 0.000), 10% CPU Elapsed application CPU time (seconds): 1.039, 3% CPUThread 0 name: Dispatch queue: com.apple.main-thread Thread 0: 0 libsystem_kernel.dylib 0x36360540 semaphore_wait_trap + 8 1 libdispatch.dylib 0x36297eee _dispatch_semaphore_wait_slow + 186 2 libxpc.dylib 0x364077b8 xpc_connection_send_message_with_reply_sync + 152 3 Security 0x2b8dd310 securityd_message_with_reply_sync + 64 4 Security 0x2b8dd48c securityd_send_sync_and_do + 44 5 Security 0x2b8ea452 __SecItemCopyMatching_block_invoke + 166 6 Security 0x2b8e96f6 SecOSStatusWith + 14 7 Security 0x2b8ea36e SecItemCopyMatching + 1742.3 啟動(dòng)/重啟超時(shí)
App由于啟動(dòng)/重啟的時(shí)間超過(guò)系統(tǒng)允許的時(shí)間限制,造成異常退出。
scene-create watchdog transgression: app exhausted real (wall clock) time allowance of 19.93 seconds, Elapsed total CPU time (seconds): 21.050 (user 21.050, system 0.000)2.4 CPU打爆
主線程死鎖、啟動(dòng)/重啟超時(shí),都可能間接導(dǎo)致CPU打爆,造成異常退出。
三、Abort問(wèn)題的根因定位
Abort問(wèn)題常常沒(méi)有明顯線索進(jìn)行問(wèn)題定位,因此,解決難度比較大。手淘曾經(jīng)歷過(guò)很多次Abort問(wèn)題數(shù)量飆升,但無(wú)從下手的事故,甚至還有一兩次發(fā)生在雙11前不久,但往往以“一群人苦逼的眾測(cè)復(fù)現(xiàn)、復(fù)現(xiàn)之后也無(wú)法確定是否真的復(fù)現(xiàn)”收?qǐng)觥?/p>
因此,我們迫切需要基于已有經(jīng)驗(yàn),形成一套完整的解決方案,快速、準(zhǔn)確地定位/解決問(wèn)題。這就需要我們從以下幾個(gè)方面著手進(jìn)行考慮:
1.Abort問(wèn)題發(fā)生的場(chǎng)景:例如,哪個(gè)頁(yè)面、什么操作。
2.Abort問(wèn)題發(fā)生的原因:例如,內(nèi)存Jetsam、主線程死鎖、啟動(dòng)/重啟超時(shí)、CPU打爆。
3.對(duì)于內(nèi)存Jetsam,需進(jìn)一步定位到是否發(fā)生了內(nèi)存泄露以及泄露的循環(huán)引用(Retain Cycle)。
4.對(duì)于主線程死鎖,需進(jìn)一步定位到卡死的堆棧。
5.對(duì)于啟動(dòng)/重啟超時(shí),以及CPU打爆,需進(jìn)一步定位到堆棧。
接下來(lái),我們以手淘的主線程死鎖問(wèn)題為例,進(jìn)行根因分析。首先,來(lái)看一下某版本手淘Abort問(wèn)題數(shù)據(jù)的總體視圖:
由于Abort問(wèn)題出現(xiàn)之前,內(nèi)存、CPU使用量正常,因此初步判斷造成異常退出的原因?yàn)橹骶€程死鎖。
查看相關(guān)日志文件,驗(yàn)證時(shí)間、線索吻合,因此可最終確定造成異常退出的原因?yàn)橹骶€程死鎖。
四、Abort問(wèn)題的系統(tǒng)性解決方案
4.1 Abort系統(tǒng)性解決方案難點(diǎn):現(xiàn)場(chǎng)捕獲
為實(shí)現(xiàn)Abort問(wèn)題的系統(tǒng)性解決方案,需充分考慮以下問(wèn)題:
1.通過(guò)signal 9殺死進(jìn)程造成的Abort問(wèn)題,往往難以通過(guò)信號(hào)量捕獲至堆棧。在這種情況下,應(yīng)如何盡可能完整地捕獲崩潰現(xiàn)場(chǎng)的關(guān)鍵信息?具體包含哪些信息?
2.App崩潰時(shí)系統(tǒng)處于極不穩(wěn)定的狀態(tài),應(yīng)如何保證崩潰現(xiàn)數(shù)據(jù)穩(wěn)定落盤(pán)?
3.在信息采集、數(shù)據(jù)捕獲的過(guò)程中,需對(duì)大量數(shù)據(jù)進(jìn)行寫(xiě)入操作,應(yīng)如何保證日志高性能寫(xiě)入?
4.在數(shù)據(jù)量較大的情況下,數(shù)據(jù)的存儲(chǔ)、上傳可能對(duì)系統(tǒng)造成較大壓力,應(yīng)如何保證數(shù)據(jù)的高壓縮率?
基于以上考慮,我們提出并設(shè)計(jì)了一套基于mmap的高性能、高壓縮率、高一致性、可自解釋的trace文件協(xié)議,作為iOS端高可用體系的數(shù)據(jù)載體。
4.1.1 mmap數(shù)據(jù)存儲(chǔ)層保證數(shù)據(jù)寫(xiě)入的高性能和高一致性
1.通過(guò)mmap將一個(gè)文件或者其它對(duì)象映射到進(jìn)程的地址空間,對(duì)內(nèi)存的操作會(huì)由內(nèi)核將數(shù)據(jù)寫(xiě)到對(duì)應(yīng)的磁盤(pán)文件上;數(shù)據(jù)寫(xiě)入的性能與內(nèi)存操作相當(dāng)(略比內(nèi)存操作高)
2.用戶進(jìn)程崩潰之后,這塊映射區(qū)仍由內(nèi)核管理,可以保證數(shù)據(jù)的一致性
4.1.2 二進(jìn)制編碼協(xié)議保證數(shù)據(jù)壓縮率最高
1.具體編碼協(xié)議
2.實(shí)測(cè)編碼在壓縮率能達(dá)到80%以上,或者直觀一點(diǎn)說(shuō),使用50k的內(nèi)存可以記錄下用戶二十分鐘內(nèi)詳細(xì)的使用記錄,包括頁(yè)面訪問(wèn)記錄、系統(tǒng)事件、秒級(jí)別的內(nèi)存、CPU數(shù)據(jù)。
4.1.3 盡可能多的記錄系統(tǒng)多維度指標(biāo)及異常事件
包括:
1.性能數(shù)據(jù),包括CPU、內(nèi)存數(shù)據(jù),用于判斷應(yīng)用當(dāng)前是不是處理overload狀態(tài)
2.大內(nèi)存申請(qǐng)
3.Retain Cycle,用于定位Jetsam Event
4.卡頓,用于定位watch dog kill
5.當(dāng)前存活VC實(shí)例數(shù)量
五、總結(jié)
在App的世界里,功能層面的差異已經(jīng)越來(lái)越難以體現(xiàn)。在這種情況下,良好的用戶體驗(yàn),往往是App致勝的關(guān)鍵。而Abort問(wèn)題對(duì)于每一個(gè)App而言,都是對(duì)用戶體驗(yàn)的最大挑戰(zhàn),需要App開(kāi)發(fā)者給予足夠的重視。
?
原文鏈接
本文為阿里云原創(chuàng)內(nèi)容,未經(jīng)允許不得轉(zhuǎn)載。
總結(jié)
以上是生活随笔為你收集整理的iOS Abort问题系统性解决方案的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 对 SolarWinds 事件更深的思考
- 下一篇: 重磅发布 | 阿里云视图计算,边缘计算的