偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

iOS應(yīng)用中多核編程和內(nèi)存管理

移動(dòng)開發(fā) iOS
在iOS中concurrency編程的框架就是GCD(Grand Central Dispatch), GCD的使用非常簡(jiǎn)單。它把任務(wù)分派到不同的queue隊(duì)列來(lái)處理。

本文集中與iOS多核編程內(nèi)存管理,為什么?因?yàn)閕Pad 2已經(jīng)是雙核CPU了!雖然iPad 1的應(yīng)用已經(jīng)不慢了,但大家完全可以使用蘋果的多核編程框架來(lái)寫出更加responsive的應(yīng)用。

多核運(yùn)算

iOS中concurrency編程的框架就是GCD(Grand Central Dispatch), GCD的使用非常簡(jiǎn)單。它把任務(wù)分派到不同的queue隊(duì)列來(lái)處理。開發(fā)者把任務(wù)代碼裝到一個(gè)個(gè)block里面,操作系統(tǒng)把這些任務(wù)代碼分派到不同的資源里去處理,一個(gè)簡(jiǎn)單的例子來(lái)說(shuō),為什么初學(xué)者寫tableview的時(shí)候,滑動(dòng)列表時(shí)總會(huì)很卡,因?yàn)楹芏喑鯇W(xué)者把圖片裝載放到main thread主線程去執(zhí)行,例如我們要滑動(dòng)暢順的話,iOS最快可以1秒內(nèi)刷新60次,如何你的一個(gè)cell的文字和圖片裝載超過(guò)1/60秒的話,自然就會(huì)卡。

所以一般我們會(huì)把圖片裝載這些需要多點(diǎn)時(shí)間的移出main thread來(lái)處理,對(duì)于用GCD來(lái)說(shuō),就是把圖片載入放到另外一個(gè)queue隊(duì)列中來(lái)異步執(zhí)行,當(dāng)資源準(zhǔn)備好了后,放回到main thread中顯示出來(lái)。main thread在GCD中就是main queue。

創(chuàng)建一個(gè)新queue隊(duì)列的代碼:

  1. dispatch_queue_t network_queue;    
  2. network_queue = dispatch_queue_create("com.myapp.network", nill);    
  3. dispatch_queue_t network_queue;  
  4. network_queue = dispatch_queue_create("com.myapp.network", nill);  

例如,我們圖片讀取放到network_queue來(lái)進(jìn)行異步執(zhí)行

  1. dispatch_async(network_queue, ^{      
  2.     UIImage *cellImage = [self loadMyImageFromNetwork:image_url];      
  3.     // 將圖片cache到本地       
  4.     [self cacheImage:cellImage];       
  5.     .....         
  6. } );    
  7. dispatch_async(network_queue, ^{    
  8.     UIImage *cellImage = [self loadMyImageFromNetwork:image_url];    
  9.     // 將圖片cache到本地    
  10.     [self cacheImage:cellImage];    
  11.     .....    
  12. } );  

dispatch_async的意思就是將任務(wù)進(jìn)行異步并行處理,不一定需要一個(gè)任務(wù)處理完后才能處理下一個(gè)。以上代碼loadMyImageFromNetwork的意思就是從網(wǎng)絡(luò)中讀取圖片,這個(gè)任務(wù)交給network_queue來(lái)處理。這樣讀取圖片的時(shí)間過(guò)長(zhǎng)也不會(huì)阻塞主線程界面的處理。

當(dāng)我們處理完圖片后,應(yīng)該更新界面,從queue的概念去設(shè)計(jì),就是要將更新界面的代碼放到main queue中去,因?yàn)閕OS里面永遠(yuǎn)是主線程來(lái)刷新重畫UI。所以代碼應(yīng)該為,

  1. dispatch_async(network_queue, ^{      
  2.     UIImage *cellImage = [self loadMyImageFromNetwork:image_url];      
  3.     // 將圖片cache到本地       
  4.     [self cacheImage:cellImage];      
  5.    // 回到主線程       
  6.    dispatch_async(dispatch_get_main_queue(), ^{      
  7.       // 顯示圖片到界面       
  8.       [self displayImageToTableView:cellImage];      
  9.    }];        
  10. } );    
  11. dispatch_async(network_queue, ^{    
  12.   UIImage *cellImage = [self loadMyImageFromNetwork:image_url];    
  13.     // 將圖片cache到本地    
  14.     [self cacheImage:cellImage];    
  15.    // 回到主線程    
  16.    dispatch_async(dispatch_get_main_queue(), ^{    
  17.       // 顯示圖片到界面    
  18.       [self displayImageToTableView:cellImage];    
  19.    }];    
  20. } );  

dispatch_get_main_queue() 函數(shù)就是返回主線程,^{} 封裝的就是任務(wù)代碼,這樣嵌套方式就可以從一個(gè)隊(duì)列queue,跳到另一個(gè)queue,就是這么簡(jiǎn)單。

我們一般可以把networking有關(guān)的代碼放到一個(gè)queue,把圖片resize的代碼放到另外一個(gè)queue,處理完后更新界面,只需要嵌套跳回到 main queue。這樣加上幾行代碼,你的程序就可以利用到系統(tǒng)多核資源,把具體的調(diào)度工作交給了操作系統(tǒng)自己來(lái)分配。有了這樣的代碼,不管你的硬件是單核,雙核還是iMac的4核,甚至8核,都可以非常好地并行處理。

內(nèi)存管理

我一直驚嘆iOS和Objective-C內(nèi)存處理能力,例如iPad版本的iWork,Pages應(yīng)用就是一個(gè)內(nèi)存處理技術(shù)應(yīng)用的鬼斧神工之作。想想256M內(nèi)存的iPad,可以帶來(lái)如此的華麗的界面同時(shí)獲得如此流暢的用戶體驗(yàn),真是不簡(jiǎn)單。原因就是iOS一直提倡開發(fā)者在有限硬件資源內(nèi)寫出最優(yōu)化的代碼,使用CPU最少,占用內(nèi)存最小。

(以下代碼適用于iOS SDK 4.1, 由于新SDK 4.2對(duì)內(nèi)存使用有新改動(dòng),所以可能有不同。。。)

1. 盡量少的UIView層

通常我們喜歡把很多控件層(UILabel,UIButton,UIView等)一起放到一個(gè)大的UIView容器來(lái)顯示我們的內(nèi)容,這個(gè)方法一般是可以的,但是如果要經(jīng)常重新刷新內(nèi)容的大區(qū)域界面,多數(shù)發(fā)生在iPad的應(yīng)用中,這個(gè)方法會(huì)帶來(lái)過(guò)多的內(nèi)存使用和動(dòng)畫的延遲(比較卡),例如,scrollview的動(dòng)畫比較卡,又或者,經(jīng)常收到內(nèi)存警告。其中一個(gè)重要原因是每個(gè)控件,特別是透明底的,會(huì)多次重新繪制(drawRect)過(guò)多。其解決辦法是,盡量將幾個(gè)控件合并到一個(gè)層上來(lái)顯示,這樣系統(tǒng)會(huì)減少系統(tǒng)調(diào)用drawRect,從而帶來(lái)性能上的提升。

很簡(jiǎn)單的一個(gè)例子,就是iNotes提供手寫功能,用戶可以在iPad屏幕上寫出不同的筆畫,開始的設(shè)計(jì)是,用戶每寫一劃,iNotes就會(huì)生成一個(gè)新的透明底UIView來(lái)保持這個(gè)筆畫,用戶寫了10筆,系統(tǒng)就生產(chǎn)了10個(gè)UIView,每個(gè)view的大小都是整個(gè)屏幕的,以便用戶的undo操作。這個(gè)方案帶來(lái)嚴(yán)重的內(nèi)存問(wèn)題,因?yàn)橄到y(tǒng)將每個(gè)層都保持一個(gè)bitmap圖,一個(gè)像素需要4bit來(lái)算,一個(gè)層的大小就是 4x1024x768 ~ 3M, 10個(gè)層就是 10x3M = 30M,很明顯,iPad很快爆出內(nèi)存警告。

這個(gè)例子最后的方案是,所有筆畫都畫在同一個(gè)層,iNotes可以保存筆畫的點(diǎn)進(jìn)行undo操作。這樣的方案就是無(wú)論用戶畫多少筆畫,界面重畫需要的資源都是一樣的。

2. 顯示最佳尺寸的圖片

很多程序員比較懶,網(wǎng)絡(luò)上拿下來(lái)的圖片,直接就用UIImageView將其顯示給用戶,這樣的后果就是,程序需要一直保存著大尺寸的圖片到內(nèi)存。解決辦法應(yīng)該是先將圖片縮小到需要顯示的尺寸,釋放大尺寸圖片的內(nèi)存,然后再顯示到界面給用戶。

3. 盡量使用圖片pattern,而不是一張大的圖片

例如,很多界面設(shè)計(jì)者喜歡在界面上放一個(gè)大底圖,但這個(gè)底圖是老是占用著內(nèi)存的,最佳方案是,設(shè)計(jì)出一個(gè)小的pattern圖,然后用這個(gè)方案顯示成底圖。

  1. UIImage *smallImage = [[UIImage alloc] initWithContentsOfFile:path];    
  2. backgroundView.backgroundColor = [UIColor colorWithPatternImage:smallImage];    
  3. [smallImage release];    
  4. UIImage *smallImage = [[UIImage alloc] initWithContentsOfFile:path];  
  5. backgroundView.backgroundColor = [UIColor colorWithPatternImage:smallImage];  
  6. [smallImage release];  

4. 使用完資源后,立即釋放

一般objective-c的習(xí)慣是,用完的資源要立即釋放,因?yàn)槊靼资裁磿r(shí)候用完某個(gè)資源的是程序員你自己。

例如,我們要讀較大的圖片,把它縮小后,顯示到界面去。當(dāng)大圖片使用完成后,應(yīng)該立即釋放。代碼如下:

  1. UIImage *fullscreenImage = [[UIImage alloc] initWithContentOfFile:path];    
  2. UIImage *smallImage = [self resizeImage:fullscreenImage];    
  3. [fullscreenImage release];    
  4. imageView.image = smallImage;    
  5. ......    
  6. UIImage *fullscreenImage = [[UIImage alloc] initWithContentOfFile:path];  
  7. UIImage *smallImage = [self resizeImage:fullscreenImage];  
  8. [fullscreenImage release];  
  9. imageView.image = smallImage

......

5. 循環(huán)中大量生成的自動(dòng)釋放autorelease對(duì)象,可以考慮使用autorelease pool封裝

代碼范例:

  1. for(UIView *subview in bigView.subviews) {    
  2.     // 使用autorelease pool自動(dòng)釋放對(duì)象池     
  3.     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];    
  4.     UIImageView *imageView = (UIImageView *)subview;    
  5.         
  6.     // subview處理代碼     
  7.     .......    
  8.     // 銷毀自動(dòng)釋放對(duì)象     
  9.     [pool  drain];    
  10. }    
  11. for(UIView *subview in bigView.subviews) {  
  12.     // 使用autorelease pool自動(dòng)釋放對(duì)象池  
  13.     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];  
  14.     UIImageView *imageView = (UIImageView *)subview;  
  15.       
  16.     // subview處理代碼  
  17.     .......  
  18.     // 銷毀自動(dòng)釋放對(duì)象  
  19.     [pool  drain];  
  20. }  

自動(dòng)釋放對(duì)象池把每個(gè)循環(huán)內(nèi)生成的臨時(shí)對(duì)象使用完后立即釋放

以上的意見是本人多年來(lái)編寫iPad/iPhone程序的經(jīng)驗(yàn),另外iOS 4.0的multi-tasking特性發(fā)布后,程序可以被調(diào)入后臺(tái)運(yùn)行,蘋果工程師的意見是,進(jìn)入后臺(tái)運(yùn)行時(shí),你的應(yīng)用應(yīng)該釋放掉能釋放的對(duì)象,盡量保持在16M左右,這樣別的程序運(yùn)行時(shí)才不容易把你的應(yīng)用擠掉。

小結(jié):iOS應(yīng)用中多核編程內(nèi)存管理的內(nèi)容介紹完了,希望本文對(duì)你有所幫助!

責(zé)任編輯:zhaolei 來(lái)源: CSDN博客
相關(guān)推薦

2011-08-22 11:07:16

IOS 開發(fā)多核內(nèi)存

2011-07-21 17:40:43

iOS 多核 內(nèi)存

2013-12-16 15:04:51

多核編程

2014-03-12 09:37:22

內(nèi)存管理autoreleaseautorelease

2018-07-23 09:26:08

iOS內(nèi)存優(yōu)化

2009-01-16 09:58:07

C#編程C#內(nèi)存管理垃圾收集

2017-03-07 10:15:35

iOS內(nèi)存管理開發(fā)

2013-12-18 16:32:27

多核編程同步模式

2013-12-16 15:09:15

多核負(fù)載

2013-12-18 16:12:26

多核編程

2011-08-16 15:13:49

IOS編程內(nèi)存

2011-07-21 14:42:45

iOS UIViewCont 內(nèi)存

2015-03-13 09:30:23

iOS內(nèi)存管理

2017-02-09 21:24:22

iOS內(nèi)存管理

2016-04-11 09:30:49

內(nèi)存管理ios開發(fā)

2013-12-18 13:26:24

多核編程

2013-07-19 13:16:26

iOS中BlockiOS開發(fā)學(xué)習(xí)內(nèi)存管理

2013-12-18 17:29:10

多核并行

2015-06-25 09:47:20

iOS內(nèi)存管理

2023-10-18 13:31:00

Linux內(nèi)存
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)