内存不足时产生的Crash Report
因为系统整体内存不足所产生的crash report,与其他的crash report 长得不太一样—这种crash report 中只会显示当时每个process 使用了多少系统资源。此外,就像前一章讲到的,你可能从Xcode 或iTunes Connect 上搜集到这种crash report,在Crashlytics 或HockeyApp 上找不到。
当我们在阅读这类型crash report 的时候,需要知道rpage 的单位,一个rpage 相当于4k 的内存。所以我们可以看到,在这台iPad Mini 上,KKBOX 用了22810 个rpage,所以KKBOX 大概使用了87 MB 的内存(22810 * 4 / 1024)。
要怎样修正这种问题呢?首先,87 MB 在iPad 上,其实不算太多,由于记忆体不足不见得是单一App 的问题,而是所有的App 共同把记忆体用完了,我们看到几个系统服务也把记忆体用得很凶,像mediaserverd(系统底层一个用来播放影音的service)用了100 MB、SpringBoard(就是iOS 装置按下Home 按钮可以看到的App 列表画面)也用了将近40 MB。所以,我们可以先试试看重新开机,把系统服务占用的资源是放掉,再来看看执行KKBOX 会不会出问题。
一个App 到底可以用多少内存?苹果一直没有说得很清楚,我们最早在iPhone 3G 上开发KKBOX 时,KKBOX 可以使用的记忆体极限大概在40 MB 左右,由于我们还要把一定比例的歌曲资料载入到内存中,所以在画面上能使用的内存就必须尽量节省。在比较后来的机种上,像iPhone 5S 或iPad 3 之后,大概用到200MB 左右都没问题,由于每个机种能用的资源都不太一样,需要的时候,我们可以写个一直alloc 记忆体的回圈做实验,不过在KKBOX 这边,我们手上的装置也没有很齐全。
如果我们真的发现App 中记忆体用太多,就只能够想办法节省记忆体。想要节省记忆体用量,最重要的原则就是—哪边用了比较多的记忆体,不要透过阅读程式码猜测,而是直接用Instrument 跑profiling 观察,确实找到记忆体的瓶颈。
至于要节省记忆体用量的作法,大概就是,如果一份资料在当下没有必要放在内存中,可以考虑先放入档案中,至于要避免产生太多view占用记忆体,可以参考内存管理Part 3 - Memory Warnings这一章。
范例crash report 如下:
Incident Identifier: 7BC7B59F-A13D-44C1-8D57-62508830C0C2
CrashReporter Key: fe242c8a27a16318ac7bbe16c6fbaaff6ce8a3a0
Hardware Model: iPad2,5
OS Version: iPhone OS 7.0.4 (11B554a)
Kernel Version: Darwin Kernel Version 14.0.0: Fri Sep 27 23:00:49 PDT 2013; root:xnu-2423.3.12~1/RELEASE_ARM_S5L8942X
Date: 2015-08-07 11:20:54 +0800
Time since snapshot: 56 ms
Free pages: 922
Active pages: 3697
Inactive pages: 2197
Speculative pages: 7
Throttled pages: 74156
Purgeable pages: 0
Wired pages: 47617
File-backed pages: 5424
Anonymous pages: 477
Compressions: 0
Decompressions: 0
Compressor Size: 0
Uncompressed Pages in Compressor: 0
Largest process: mediaserverd
Processes
Name <UUID> rpages recent_max fds [reason] (state)
MobileMail <b3574f4bded1315cb2e50e5de205be48> 1113 1113 200 [vm-pageshortage] (resume) (continuous)
tccd <1fea8c5a71943151b5cd304c7eb0fd8c> 170 170 200 [vm-pageshortage] (daemon)
kbd <be2d64e41bf43e48a09a23fb129eb0b4> 381 381 200 [vm-pageshortage] (daemon)
KKBOX <8367b00614e735f5861044b98c96cd1c> 22810 22810 200 [vm-pageshortage] (frontmost) (resume)
ptpd <db9048c36f6c3c18a7330fc96d93a0cf> 657 657 200 (daemon)
identityservices <18cc20db2e4739a782cc8e38e03eff52> 349 349 200 (daemon)
syslogd <6539f4cf4dcf34daadf1d99991926680> 157 157 50 (daemon)
powerd <0a253ac2a99236809422214be1700bc0> 121 121 100 (daemon)
imagent <bef102e1faef39209926fb25f428a71e> 298 298 100 (daemon)
iaptransportd <42faa147f61a314bb735e239f445efaf> 219 219 50 (daemon)
mDNSResponder <8922e9954d893eb9a1ab27ca4723bbab> 228 228 100 (daemon)
apsd <0dd1fd7c2edc3cf9899a4830541c1bac> 468 468 100 (daemon)
dataaccessd <5da732b6ce6935f2928461a022101aba> 1228 1228 200 (daemon)
mediaremoted <476eb521b8423428b4e6df20d3fe4091> 327 327 50 (daemon)
wifid <a5cf99e5a0f032a69bc2f65050b44291> 1859 1859 200 (daemon)
mediaserverd <71101024312538ccae5799b88681e38d> 25807 25807 200 (daemon)
sharingd <a95c2cea41b43cc69b0bbe9a03730d45> 460 460 200 (daemon)
calaccessd <77a5672f2f653f64acf7367126a8d173> 420 420 200 (daemon)
itunesstored <c52ea3e4aceb398e9a98ff595c17669f> 1576 1576 200 (daemon)
locationd <c31643022d833911b8b7461fd3964bd5> 2497 2497 200 (daemon)
syslog_relay <c4c1e88d92a537888b15d6118c5fa1d1> 107 107 200 (daemon)
SpringBoard <3c0e305139b331c6b37d2e9516f5804f> 10207 10207 200
backboardd <d61df126c4673b25bbfe5d9024be1d48> 13495 13495 50 (daemon)
aggregated <a5dda46586ba3a3cbb298bd8aa545e50> 666 666 50 (daemon)
lockdownd <6f28a28a0025348aa5361078e41914e3> 340 340 100 (daemon)
fairplayd.A2 <6cae0c124e1830598a43f6b4d790917f> 141 141 100 (daemon)
configd <c57db43e53a73f8a9360f4d0d9001704> 686 686 100 (daemon)
fseventsd <5c909a70b62f33c8856e3158834ba071> 336 336 100 (daemon)
BTServer <3933a8148924316b9f19dd3d10a23f00> 3891 3891 100 (daemon)
distnoted <38616bd8864034e7bc741f8bd7313349> 1187 1187 100 (daemon)
UserEventAgent <a3c7e56924ec3690a994a75a0ea79ee8> 850 850 100 (daemon)
networkd <84dfdb49c24132fa8dd10520deb16645> 523 523 100 (daemon)
filecoordination <4fa03f2b93363668a1159715de4b0270> 186 186 200 (daemon)
EscrowSecurityAl <65547599d6d331f2aec702509cbb1079> 175 175 200 (daemon)
itunescloudd <9a38b56ee4fd3c308766da99af8eeaed> 932 932 200 (daemon)
touchsetupd <02780826b4263a7498bda167721b5f8c> 163 163 200 (daemon)
afcd <5c18557c26f73b88a54ad94f3cd06d0c> 113 113 200 (daemon)
notification_pro <852af3fe832e3cc3a3f31d05511a5482> 124 124 200 (daemon)
cplogd <148e9e2ff86130ecb63423c183f68da5> 137 137 200 (daemon)
pasteboardd <6bb2d8a2beb530b095c82dc2c1cda0f7> 119 119 200 (daemon)
wirelessproxd <46066fc432663d45ab7e055082fe0bd6> 11 11 200 (daemon)
CommCenterClassi <b836b786e0cb3785a18a94e9b13c9991> 363 363 50 (daemon)
notifyd <35afacabfed73771889e72a017479709> 251 251 100 (daemon)