注意:這個工具非常有用,文本也是一個超長文
Allocations初始界面
Allocations:檢測一個進程(選擇自己的app)內(nèi)存分配和使用情況等
我們啟動Allocations后得到一個初始界面
簡單說一下上圖的3個地方
1:這里有兩個部分了臭挽,因為官方說了Allocations(上面)和垃圾數(shù)據(jù)占用(下面)一起展示更好分析
2:一個列表捂襟,展示了哪些方法\部分消耗了多少內(nèi)存,前面的鉤鉤上會在1部分顯示出主柱狀圖欢峰,自己點一下就知道了葬荷,不截圖
3:設(shè)置和擴展功能,文章后面慢慢講
開始分析列表
我先隨意的在自己app中點擊纽帖,跳轉(zhuǎn)等操作宠漩,然后截個圖如下
我們可以驚訝的看到All Heap Allocations(真實內(nèi)存)只有23.02,而All Anonymous VM(虛擬內(nèi)存:為程序分配的虛擬內(nèi)存,當程序有需要的時候懊直,能夠及時為程序提供足夠的內(nèi)存空間扒吁,而不會現(xiàn)用現(xiàn)創(chuàng)建)高達91.06,所以手機分配給我們的內(nèi)存是114.08室囊;我們現(xiàn)在不檢測內(nèi)存泄漏(是另外一個工具)雕崩,所以我們盡量優(yōu)化VM(因為不是app真實占用的內(nèi)存,只是系統(tǒng)分配的)融撞,而VM主要由以下三部分組成(我會把三部分都優(yōu)化完了后再運行截圖)
VM:ImageIO_PNG_Data
關(guān)于這個問題我在google中找到了解釋盼铁,說到
Replace:
background.image = [UIImage imageNamed:@"*.png"];
With:
background.image = [UIImage imageWithContentsOfFile:[[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/*.png"]];
and now the ImageIO_PNG_Data's will be released when the view controller is dismissed.
我后面在我工程中搜索了一下imageNamed,確實有很多地方使用了尝偎,所以我們加載圖片正確的思路應(yīng)該是這樣
1:對于大的圖片且偶爾需要顯示的應(yīng)放到工程目錄下饶火,不要放到Assets.xcassets中鹏控;并使用imageWithContentsOfFile加載不讓系統(tǒng)緩存
2:對于經(jīng)常需要展示的小圖片放到Assets.xcassets中讓系統(tǒng)緩存,使用imageNamed加載
所以我改了一些地方肤寝,比如
imageView.image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:nameArr[index] ofType:@"png"]];
//imageView.image = [UIImage imageNamed:nameArr[index]];
VM:CG raster data
關(guān)于這個問題我在google中找到了解釋当辐,這是SDWebImage的問題
* Decompressing images that are downloaded and cached can improve peformance but can consume lot of memory.
* Defaults to YES. Set this to NO if you are experiencing a crash due to excessive memory consumption.
所以我們需要在Appdelegate中設(shè)置一下
[[SDImageCache sharedImageCache] setShouldDecompressImages:NO];
[[SDWebImageDownloader sharedDownloader] setShouldDecompressImages:NO];
[[SDImageCache sharedImageCache] setShouldCacheImagesInMemory:NO];
VM:CoreAnimation
這個問題在google搜索的時候沒有明顯的答案,我們先查看一下詳細列表
Found out that animation caused by the inner pages.
Inside the pageViewController(viewController that added to the scrollView as a page) on viewWillDisappear:(BOOL)animated method I added this
for (CALayer* layer in [self.view.layer sublayers]) {
[layer removeAllAnimations];
}
it resolved the problem.
其中的Found out that animation caused by the inner pages我們還是需要在擴展信息中查看能不能定位到某個頁面(我不知道怎么定位寺晌,如果你知道請一定回復(fù)我),所以我在我剛才進入過的界面全部實現(xiàn)了如上方法
看看優(yōu)化結(jié)果
這時候我們重新啟動Allocations澡刹,然后重復(fù)上面隨意的在自己app中點擊呻征,跳轉(zhuǎn)等操作,然后截圖如下
我們發(fā)現(xiàn)一個好的現(xiàn)象VM:CG raster data明顯減少了罢浇;同時我們得到一個壞現(xiàn)象陆赋,其他兩項并沒有明顯變化,那我們繼續(xù)分析什么原因嚷闭,不過不要著急攒岛,我們先來看看右下方都有哪些功能
Record Settings
Launch Configuration for All Allocations
所有的Allocations啟動如下配置:
Discard unrecorded data upon stop:當用戶點擊停止的時候丟棄沒有記錄的數(shù)據(jù),勾不勾無所謂
Discard events for freed memory:當內(nèi)存被釋放的時候丟棄事件(也就是列表中不顯示已被釋放內(nèi)存所關(guān)聯(lián)的事件)
Only track VM allocations:只捕獲虛擬內(nèi)存的項胞锰,不勾灾锯,因為我們還是需要看看真實內(nèi)存占用的
這里我們需要把第一、二個勾上
Launch Configuration for Heap Allocations
對所有的真實內(nèi)存Allocations啟動如下配置(如果你鉤中了Only track VM allocations嗅榕,這一欄是沒辦法操作的):
Record reference counts:記錄引用計數(shù)
Identity virtual C++ objects:標記虛擬c++對象顺饮,這個鉤上可以檢測openGL等庫
Enable NSZombie detection:檢測僵尸對象,鉤上可以發(fā)現(xiàn)有沒有對已釋放的對象發(fā)送消息
Recorded Types
這個我就不需要解釋了凌那,你需要捕獲什么類型的事件就鉤上兼雄,提供了簡單的正則
Dispalay Settings
Track Display
決定上面將要顯示什么內(nèi)容
Current Bytes:顯示字節(jié)數(shù)量
Allocation Density:Allocation數(shù)量
Active Allocation Distribution:新激活的Allocation數(shù)量
Generation Analysis
這個功能是非常有用的,一般是這樣用的:進入一個頁面前mark一下帽蝶,在退出這個頁面的時候再mark一下可以比較哪些內(nèi)容增加了赦肋,就可以具體分析哪些內(nèi)存沒有被釋放;比如我們要進入日程界面的時候我點了一下mark
顯示了Growth(相比上一次增加的量)為27.48嘲碱,也就是第一次真實內(nèi)存和虛擬內(nèi)存之和金砍;我們在日程界面操作一陣子之后我們再點擊mark截圖
Allocation Lifespan
需要記錄哪些Allocation
All Allocations:所有的
Created & Persistent:創(chuàng)建且存活的
Created & Destroyed:創(chuàng)建且被銷毀的
我們目前只關(guān)心存活的麦锯,所以我們鉤上第二個
Allocation Type
記錄的Allocation類型
All Heap & Anonymous VM:所有真實內(nèi)存和虛擬內(nèi)存恕稠,我通常選這個分析
All Heap Allocations:所有真實內(nèi)存
All VM Regions:所有分配過的虛擬內(nèi)存
這里的選擇將會影響到列表,比如我選擇All VM Regions
Call Tree
這里的功能需要我們把列表展示類型切換成Call Trees扶欣,能夠非常清晰的看到調(diào)用樹
不過一般我們需要勾選一些選項鹅巍,因為默認的實在看不出什么東西
Separate by Category:按照類別隔開千扶,我們鉤上看看效果
Separate by Thread:按照線程劃分骆捧,我個人不是很喜歡這種劃分澎羞,因為我不是很關(guān)心線程
Invert Call Tree:反轉(zhuǎn)調(diào)用,我們給一張對比圖就不需要解釋了
Hide System Libraries:這個似乎是必鉤的妆绞,因為我們目前只關(guān)心自己的方法,不關(guān)心系統(tǒng)的
Flatten Recursion:扁平化遞歸枫攀,我暫時還不知道是干嘛的括饶,網(wǎng)上也沒有搜到,不過我還是鉤上了来涨,聽著是一個不錯的功能
Call Tree Constraints
這個我就不需要講了图焰,是對列表中的數(shù)據(jù)進行過濾,可以是數(shù)量和大斜钠技羔;比如我只關(guān)心100以內(nèi)的數(shù)據(jù)
Data Mining
數(shù)據(jù)挖掘,這是一個很具有噱頭的功能卧抗;官網(wǎng)給了這么一個解釋
Allows you to filter through the collected data for specific symbols and libraries.
就是可以過濾掉你不看的庫藤滥、符號調(diào)用
點擊Symbol、Library會自動把你選中的行的符號社裆、庫加到小框中
Extended Detail
這個我其實已經(jīng)介紹過了张漂,對于Allocations來說是看某一條數(shù)據(jù)的調(diào)用棧等信息
到現(xiàn)在我們只有一種列表展示沒有介紹了晶默,我們來看一眼
相對于Statistics來說多了調(diào)用庫和方法的展示
繼續(xù)優(yōu)化
剛才說到了,我們只對VM:CG raster data的優(yōu)化表示滿意航攒,接下來我們繼續(xù)優(yōu)化VM:CoreAnimation和VM:ImageIO_PNG_Data
VM:ImageIO_PNG_Data優(yōu)化
前面說到我們把加載大圖片的方法換成了imageWithContentsOfFile但是效果不明顯磺陡,現(xiàn)在我們就來看看具體是哪個方法產(chǎn)生了大量的虛擬內(nèi)存,下面是步驟
//_pageScrollView是一個滾動視圖漠畜,用來加載本地圖片
...
//加入圖片
for (int index = 0; index < nameArr.count; index ++) {
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(index * pageScrollImagewidth, 0, pageScrollImagewidth, pageScrollImageheight)];
NSString *imageFile = [NSString stringWithFormat:@"%@/%@.png",[[NSBundle mainBundle] resourcePath],nameArr[index]];
@autoreleasepool {
imageView.image = [UIImage imageWithContentsOfFile:imageFile];
}
// imageView.image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:nameArr[index] ofType:@"png"]];
// imageView.image = [UIImage imageNamed:nameArr[index]];
[_pageScrollView addSubview:imageView];
}
...
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
for (UIView *viewView in _pageScrollView.subviews) {
[viewView removeFromSuperview];
}
_pageScrollView = nil;
}
按照這個方法后币他,效果還是很明顯的,之前是33.95(看文章前面的圖)
優(yōu)化VM:CoreAnimation
我們同樣用Generations檢測出了這個問題
前面說到我們谷歌到可以采用下面的方法減少
for (CALayer *layer in self.view.layer.sublayers) {
[layer removeAllAnimations];
}
但是證明幾乎沒用憔狞,那我們只好繼續(xù)谷歌看看蝴悉,按照上面的方法,我們在谷歌輸入關(guān)鍵字CA::Render::Shmem::new_shmem(unsigned long)進行搜索瘾敢,我們從搜索的結(jié)果可以得知這是一個很多原因都會導(dǎo)致的結(jié)果拍冠;其中在這篇文章有兩段描述
the solution is to reduce that space to an absolute minimum.
//把控件的范圍設(shè)置到最小
...
I am having the same issue. I will try what you suggested with the size.
But, maybe changing the background color from clearColor could
correct the issue as well.
//改變視圖的背景顏色
我試了改變背景顏色尿这,沒什么作用
[[UIView appearance] setBackgroundColor:[UIColor whiteColor]];
[[UIView appearance] setBackgroundColor:[UIColor clearColor]];
所以我們就暫時不解決這個了,我后面解決了會在這里進行補充庆杜,VM:Animation優(yōu)化是一個大問題射众,可能需要一篇文章單獨講
看另一部分
接下來我們來看看這個視圖是干什么用的,使用的時候需要手動捕獲(或者你鉤上Automatic Snapshotting自動定時捕獲)一次左下角列表才有數(shù)據(jù)
Dirty Size:臟數(shù)據(jù)大谢尾啤(沒辦法被重復(fù)使用)
Swapped Size:交換空間大小
Resident Size:固定數(shù)據(jù)大小
關(guān)于這三個名字的解釋叨橱,你可以看看這里,所以我們得知這條數(shù)據(jù)是有異常的
又從這里得知我們不需要管這個問題,因為這時XCode工具自身的郑临,不是我們程序的
所以我們來看下一個問題
Regoins Map
這個視圖公你,主要是把每一條數(shù)據(jù)的地址段和調(diào)用路徑給你顯示出來了踊淳,我很少用這個視圖,不過能看到path還是不錯的
Allocations一般來做什么
其實文本已經(jīng)大致講了一下陕靠,Allocations對app優(yōu)化非常有用迂尝,通常是拿來分析內(nèi)存增加(不一定是內(nèi)存泄漏)和app中各部分占用內(nèi)存問題,當我們得知哪個內(nèi)存占用比較多剪芥,我們直接進行優(yōu)化即可減少內(nèi)存占用問題
本文一直在討論如何減少VM的占用垄开,你接下來可以分析Heap占用