iOS性能優(yōu)化之CPU钉赁、GPU的優(yōu)化(一)

面試的時候總會遇到以下問題:

1.你在項目中是怎么優(yōu)化內(nèi)存的?
2.優(yōu)化你是從哪幾方面著手携茂?
3.列表卡頓的原因可能有哪些你踩?你平時是怎么優(yōu)化的?
4.遇到tableview卡頓嗎讳苦?會造成卡頓的原因大致有哪些带膜?

一、CPU和GPU

在屏幕成像的過程中鸳谜,CPU和GPU起著至關(guān)重要的作用膝藕。

CPU(中央處理器)
對象的創(chuàng)建和銷毀,對象屬性的調(diào)整咐扭、布局計算芭挽、文本的計算和排版滑废、圖片格式轉(zhuǎn)碼和解碼、圖像的繪制(Core Graphics)
GPU(圖形處理器)
紋理的渲染(OpenGL)

那CPU和GPU是怎么協(xié)作呢袜爪?
一個app的展示會包含很多內(nèi)容蠕趁,諸如,label辛馆,imageview俺陋,button等等。這些控件的位置昙篙,大小腊状,顏色則都是由CPU來計算,計算完成后CPU會將這些數(shù)據(jù)提交給GPU來進行渲染瓢对,只有經(jīng)過GPU的渲染才能顯示在屏幕上寿酌。GPU做的操作則是:將收到的數(shù)據(jù)轉(zhuǎn)成屏幕能顯示的數(shù)據(jù)格式,所以要進行渲染的操作硕蛹。渲染的操作是直接放在幀緩存(緩存區(qū))醇疼。然后視頻控制器從緩存區(qū) 讀取的數(shù)據(jù)顯示在屏幕上。就完成了一個顯示的操作法焰。

顯示流程.png
在iOS中是雙緩存機制秧荆,有前幀緩存、后幀緩存

二埃仪、屏幕成像原理

在屏幕顯示過程中是有信號發(fā)送的乙濒。一幀一幀的。

發(fā)出垂直同步信號(VSync)時卵蛉,即將顯示一頁的數(shù)據(jù)颁股。水平同步信號(HSync)發(fā)出時,就一行一行的顯示傻丝。
信號.png

三甘有、卡頓的原因

屏幕內(nèi)容是怎么顯示到屏幕上的?
CPU(紅色)——>GPU(藍色)
1.CPU完成計算葡缰,提交給GPU渲染亏掀,這是來個垂直同步信號,則會將渲染的內(nèi)容顯示到屏幕上泛释。
2.CPU計算時間正常滤愕,CPU渲染時間短,等待VSync
3.CPU計算時間正沉#或慢间影,GPU渲染時間長茄茁,這時來了VSync宇智,而這一幀還沒有渲染完,那么就會出現(xiàn)掉幀現(xiàn)象随橘,屏幕回去顯示上一幀的畫面锦庸。這樣就產(chǎn)生了卡頓机蔗。
4.而當(dāng)下一幀VSync出現(xiàn)時,丟掉的那一幀畫面才會出現(xiàn)甘萧。


掉幀.png
卡頓解決的主要思路:
盡可能減少CPU萝嘁、GPU資源的消耗扬卷。
按照60FPS的刷幀率,每隔16ms就會有一次VSync信號怪得。

四咱枉、卡頓優(yōu)化-CPU

1.盡量用輕量級的對象,比如用不到事件處理的地方徒恋,可以考慮使用CAlayer取代UIView蚕断;能用基本數(shù)據(jù)類型,就別用NSNumber類型亿乳。
2.不要頻繁地跳用UIVIew的相關(guān)屬性,比如frame葛假、bounds、transform等屬性聊训,盡量減少不必要的修改
3.盡量提前計算好布局,在有需要時一次性調(diào)整對應(yīng)的布局魔眨,不要多次修改屬性
4.Autolayout會比直接設(shè)置frame消耗更多的CPU資源
5.圖片的size最好剛好跟UIImageView的size保持一致
6.控制一下線程的最大并發(fā)數(shù)量
7.盡量把耗時的操作放到子線程
8.文本處理(尺寸的計算酿雪,繪制)
9.圖片處理(解碼遏暴、繪制)

//圖片解碼的代碼
- (void)image
{
    UIImageView *imageView = [[UIImageView alloc] init];
    imageView.frame = CGRectMake(100, 100, 100, 56);
    [self.view addSubview:imageView];
    self.imageView = imageView;

    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        // 獲取CGImage
        CGImageRef cgImage = [UIImage imageNamed:@"timg"].CGImage;

        // alphaInfo
        CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(cgImage) & kCGBitmapAlphaInfoMask;
        BOOL hasAlpha = NO;
        if (alphaInfo == kCGImageAlphaPremultipliedLast ||
            alphaInfo == kCGImageAlphaPremultipliedFirst ||
            alphaInfo == kCGImageAlphaLast ||
            alphaInfo == kCGImageAlphaFirst) {
            hasAlpha = YES;
        }

        // bitmapInfo
        CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host;
        bitmapInfo |= hasAlpha ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst;

        // size
        size_t width = CGImageGetWidth(cgImage);
        size_t height = CGImageGetHeight(cgImage);

        // context
        CGContextRef context = CGBitmapContextCreate(NULL, width, height, 8, 0, CGColorSpaceCreateDeviceRGB(), bitmapInfo);

        // draw
        CGContextDrawImage(context, CGRectMake(0, 0, width, height), cgImage);

        // get CGImage
        cgImage = CGBitmapContextCreateImage(context);

        // into UIImage
        UIImage *newImage = [UIImage imageWithCGImage:cgImage];

        // release
        CGContextRelease(context);
        CGImageRelease(cgImage);

        // back to the main thread
        dispatch_async(dispatch_get_main_queue(), ^{
            self.imageView.image = newImage;
        });
    });
}

五指黎、卡頓優(yōu)化-GPU

1.盡量減少視圖數(shù)量和層次
2.GPU能處理的最大紋理尺寸是4096x4096,一旦超過這個尺寸醋安,就會占用CPU資源進行處理墓毒,所以紋理盡量不要超過這個尺寸
3.盡量避免段時間內(nèi)大量圖片的顯示亲怠,盡可能將多張圖片合成一張圖片顯示
4.減少透明的視圖(alpha<1),不透明的就設(shè)置opaque為yes
5.盡量避免出現(xiàn)離屏渲染

在OpenGL中团秽,GPU有2種渲染方式:

1.On-SCreen Rendering:當(dāng)前屏幕渲染,在當(dāng)前用語顯示的屏幕緩沖區(qū)進行渲染操作习勤。
2.Off-Screen Rendring: 離屏渲染,在當(dāng)前屏幕緩沖區(qū)以外新開辟一個緩沖區(qū)進行渲染操作图毕。

離屏渲染消耗性能的原因:

1.需要創(chuàng)建新的緩沖區(qū);
2離屏渲染的整個過程予颤,需要多次切換上下文環(huán)境,先是從當(dāng)前屏幕切換到離屏荣瑟;等到離屏渲染結(jié)束以后,將離屏緩沖區(qū)的渲染結(jié)果顯示到屏幕上笆焰,又需要將上下文環(huán)境從離屏切換到當(dāng)前屏幕

哪些操作會出發(fā)離屏渲染?

1.光柵化嚷掠,layer.shouldRasterize = YES
2.遮罩,layer.mask
3.圓角不皆,同時設(shè)置layer.maskToBounds = Yes,Layer.cornerRadis 大于0
考慮通過CoreGraphics繪制裁剪圓角霹娄,或者美工提供圓角圖片
4.陰影,layer.shadowXXX
如果設(shè)置了layer.shadowPath就不會產(chǎn)生離屏渲染

六.卡頓檢測

平時所說的“卡頓”主要是因為在主線程執(zhí)行了耗時的操作犬耻。
可以添加Observer到主線程RunLoop中,通過監(jiān)聽RunLoop狀態(tài)切換的耗時枕磁,以達到監(jiān)聽卡頓的目的
推薦一個庫:LXDAppFluecyMonitor

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子排苍,更是在濱河造成了極大的恐慌,老刑警劉巖淘衙,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件腻暮,死亡現(xiàn)場離奇詭異幔翰,居然都是意外死亡西壮,警方通過查閱死者的電腦和手機叫惊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來霍狰,“玉大人,你說我怎么就攤上這事蔗坯。” “怎么了宾濒?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長绘梦。 經(jīng)常有香客問我,道長卸奉,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任凝颇,我火速辦了婚禮,結(jié)果婚禮上拧略,老公的妹妹穿的比我還像新娘。我一直安慰自己尚辑,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布月褥。 她就那樣靜靜地躺著弛随,像睡著了一般宁赤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上决左,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天,我揣著相機與錄音佛猛,去河邊找鬼。 笑死继找,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的婴渡。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼边臼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了柠并?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤亿傅,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后瘟栖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡酬滤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年寓涨,在試婚紗的時候發(fā)現(xiàn)自己被綠了盯串。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片戒良。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出几缭,到底是詐尸還是另有隱情,我是刑警寧澤年栓,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站某抓,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏否副。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一负甸、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧痹届,春花似錦打月、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽秘通。三九已至,卻和暖如春肺稀,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背话原。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留繁仁,地道東北人。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓黄虱,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子晤揣,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容