<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Jack Jiang

    我的最新工程MobileIMSDK:http://git.oschina.net/jackjiang/MobileIMSDK
    posts - 494, comments - 13, trackbacks - 0, articles - 1

    本文由微信客戶端團(tuán)隊rhythm分享,原題“視頻號直播:如何進(jìn)一步降低功耗占用?”,本文有修訂和改動。

    1、引言

    功耗優(yōu)化一直是 app 性能優(yōu)化中讓人頭疼的問題,尤其是在直播這種用戶觀看時長特別久的場景。怎樣能在不影響主體驗的前提下,進(jìn)一步優(yōu)化微信iOS端視頻號直播的功耗占用,本文給出了一個不太一樣的答案。

     
     
    技術(shù)交流:

    (本文已同步發(fā)布于:http://www.52im.net/thread-4507-1-1.html

    2、問題背景

    問題的起因是我們測試統(tǒng)計發(fā)現(xiàn)帶有點贊的直播會比無點贊動畫的直播 GPU 占用要高將近一倍,同時 FPS 差異也很大。

    高刷屏下,PerfDog 測試顯示,有點贊情況下的大部分視頻號直播居然是以60fps在跑,這導(dǎo)致了極高的GPU占用。

    但我們根本沒有60fps 這么高的直播流,且絕大部分直播流都只有30fps 而已,少部分也就最高60fps,怎么到了設(shè)備上就達(dá)到了60fps?

    而且這還是我們開啟了強(qiáng)制低幀率UIViewAnimationOptionPreferredFramesPerSecond30后的效果,沒開之前直接奔120fps 去了。

    如下圖所示 PerfDog 數(shù)據(jù)顯示在 13 pro max上直播點贊期間 FPS 直奔120:

    正常情況下,視頻號直播里大部分主播開播流基本都是30fps 以內(nèi),也就是正常情況下我們只需要維持30fps 渲染,就能保持好流程的用戶體驗。

    那為什么這里降幀后依舊會出現(xiàn)60fps 呢?

    經(jīng)過一系列排查我們發(fā)現(xiàn)這是由于直播的點贊動畫導(dǎo)致的高幀率,如果去掉動畫后 FPS 就會回到正常情況下了,且 GPU 占用也有了明顯下降。

    這到底是怎么回事?我們是否可以降動畫的幀率降低到某個值來去優(yōu)化我們整體的 GPU 占用呢?

    3、知識儲備1:iOS中的動畫分類

    在iOS中,大部分動畫的本質(zhì)就是根據(jù)輸入的時間戳,返回對應(yīng)屬性的動畫參數(shù),從而移動圖像,達(dá)到運動的效果。根據(jù)動畫 api 實現(xiàn)方式的特點我們可以把動畫 api 劃分為如下幾類。

    3.1UIView block animation

    基于 「+[UIView animateWithDuration:delay : options:animations:completion:]」 動畫api驅(qū)動的動畫,特點是所有動畫都在 animations block 里同步觸發(fā),可以方便的設(shè)置任何屬性動畫。

    [UIView animateWithDuration:duration

                                 delay:0

                               options:option

                            animations:^{

                                view.top -= offsetY;

                                view.left -= offsetX;

                            }

                            completion:completion];

    3.2CAAnimation

    基于 「CAAnimation api」 直接觸發(fā)提交的動畫,例如:

    CABasicAnimation *ani_position = [CABasicAnimation animationWithKeyPath:@"position"];

    ani_position.fromValue = @(val.position.from);

    ani_position.toValue = @(val.position.to);

    [view.layer addAnimation:group forKey:key];

    3.3Timer

    基于 「NSTimer/GCD」 觸發(fā)的動畫,例如定時去修改某個 imageView.image,使得它能定期變換的效果。基于 「CADisplayLink」 觸發(fā)的動畫,和基于 NSTimer 觸發(fā)類似,只不過這個 timer 源是和渲染保持一致的,能夠做到更流暢更貼合。

    比如我們要實現(xiàn)自定義的 UIScrollView 動畫,就可以基于 CADisplayLink 來做。

    3.4UIViewPropertyAnimator

    「UIViewPropertyAnimator」是iOS10開始蘋果推動的新的動畫api,相比 UIView block animation 可以更靈活的控制動畫的過程。

    [UIViewPropertyAnimator runningPropertyAnimatorWithDuration:duration

                                         delay:0

                                       options:option

                                    animations:^{

                                        view.top -= offsetY;

                                        view.left -= offsetX;

                                    }

                                    completion:completion];

    4、知識儲備2:iOS中的動畫渲染

    iOS中的動畫或者 UIView 的修改到底是怎么被渲染到屏幕上去的?

    4.1Core Animation Pipeline

    iOS 的 UI 更新和動畫操作都離不開 Core Animation 和 UIKit,他們的底層都是 QuartzCore,所有的 UI 刷新和動畫提交都會打包成對應(yīng)的 CA::Transaction 和 CAAnimation 對象并提交給 Render Server 去處理。

    App 本身并不負(fù)責(zé)渲染,渲染是由獨立的進(jìn)程 Render Server 來負(fù)責(zé)的,Render Server 最終調(diào)用 -[AGXG14FamilyRenderContext drawIndexedPrimitives:indexCount:indexType:indexBuffer:indexBufferOffset:] 等 GPU 接口來完成 GPU 任務(wù)的提交,最終觸發(fā)屏幕更新操作。

    整體過程大概如下:

    • 1)App 處理事件,例如 touch 事件或者 displaylink timer 事件;
    • 2)App 完成視圖的 layout、圖像 decode 等操作,并觸發(fā) CA::Transaction 提交;
    • 3)Render Server 接收 App 提交的 Transction 和圖片數(shù)據(jù),Render Server 可直接跨進(jìn)程訪問 App 進(jìn)程的位圖內(nèi)存資源,并最終觸發(fā) GPU 調(diào)用;
    • 4)GPU 最終完成了圖像的渲染并顯示到屏幕 Display。

    4.2Render Server

    如下圖所示,最終的上屏任務(wù)提交操作是由 Render Server 也即 backboardd 進(jìn)程來最終觸發(fā)的。

    在 iOS 中 Render Server 通常指的是 backboardd 進(jìn)程,backboardd 進(jìn)程是一個與 SpringBoard 守護(hù)進(jìn)程一起運行的守護(hù)進(jìn)程。

    它在 iOS 6 中引入,旨在減輕 Springboard 的一些職責(zé),主要是事件處理的職責(zé)。它主要負(fù)責(zé)把 touch 事件分發(fā)到 app 進(jìn)程以及處理 app 進(jìn)程觸發(fā)的動畫和UI更新操作。

    如上圖所示,time profiler 里我們能清晰看到 backboardd 進(jìn)程在處理來自 app 進(jìn)程的圖像提交操作。

    微信直播之前就遇到過好幾次 Render Server 命中了 gpu io fence 導(dǎo)致系統(tǒng)全局卡死的問題。

    如下圖 ips 文件日志所示:

    4.3Render Loop

    Render Loop 是包括了從 app 到 Render Server 再最終到屏幕的一系列任務(wù)觸發(fā),刷新,更新與提交,直到上屏的一系列過程,是對渲染管道的進(jìn)一步封裝,類似于一套 runloop 循環(huán)機(jī)制,能隨時的處理輸入和輸出。

    4.4動畫渲染

    當(dāng)我們調(diào)用-[UIView animateWithDuration:animations:] api觸發(fā)動畫后,整體動畫渲染過程如下圖3步所示。

    4.5幀率

    幀率即 FPS(frames per second),每秒渲染了多少幀,正常情況下只要我們定期提交一次 opengl 上屏 [curContext presentRenderbuffer:GL_RENDERBUFFER] 就會觸發(fā)一幀的上屏操作,這就回導(dǎo)致 FPS 發(fā)生變化,也最終影響了 app 的性能占用。

    FPS 越高對于游戲等高清視頻效果就更細(xì)膩更好,但是并不是所有情況都需要高 FPS,部分情況下高 FPS 反而導(dǎo)致了無用的功耗但并沒有帶來更好的體驗。

    4.6屏幕刷新率

    對于 iOS15/iPhone 13以前的設(shè)備,屏幕是固定的刷新率,在這之后 iPhone 13和 iPad Pro 后引入了高刷屏,并且支持了動態(tài)刷新率。

    對于直播場景 FPS 有3個:

    • 1)視頻流 FPS;
    • 2)Render Server FPS;
    • 3)屏幕 FPS。

    對于非可變刷新率的屏幕,我們可以盡可能減少 GPU 的幀率(即 Render Server 提交的 FPS)來達(dá)到降低 GPU 功耗的目的,對于可變刷新率的屏幕,那只要減少了 GPU 幀率就自然而然也減少了屏幕的刷新率,使得屏幕和 GPU 功耗都下降了。

    在我們遇到的問題中,我們的視頻流 FPS 是25,那么我們預(yù)期的最終 GPU FPS 和屏幕 FPS 理應(yīng)同理也是接近25才是,而這里卻達(dá)到了60fps,說明了有重復(fù)的內(nèi)容幀一直被 Render Server 重復(fù)的復(fù)制并提交給 GPU,導(dǎo)致了畫質(zhì)細(xì)節(jié)沒有增加,但頻繁的拷貝渲染造成了更高的 GPU 占用。這就是我們的問題所在。

    5、知識儲備3:iOS中的動畫降幀

    5.1概述

    結(jié)合上文,我們要解決直播幀率異常升高的問題,就需要解決點贊動畫的高幀率問題。

    很幸運,蘋果在 iOS15提供了一個 CAAnimation 的 api,即-[CAAnimation preferredFrameRateRange],它接受3個參數(shù)分別指定minimum 幀率,maximum 幀率,以及 preferred 幀率,基于這個api我們可以對于 CAAnimation 動畫設(shè)置幀率。

    蘋果的建議是把動畫分為了如下幾檔:

    5.2CAAnimation 降幀原理

    iOS15開始蘋果引入了 CAFrameRateRange 相關(guān) api 來供 app 去設(shè)置 CADisplayLink 和 CAAnimation 的 preferredFrameRateRange,以方便調(diào)節(jié)幀率,達(dá)到在高刷機(jī)上能進(jìn)一步降低功耗的目的。

    那它又是如何工作的呢?

    首先需要明確 iOS15后 CAAnimation 和 CADisplayLink 的幀率控制底層都是一致的,也就是都是 CA:: Display: : DisplayLinkItem 來驅(qū)動觸發(fā)的。而動畫的本質(zhì)就是根據(jù)時間的輸入來得到對應(yīng)的動畫 fraction 并觸發(fā)對應(yīng)進(jìn)度的動畫修改,再提交上屏完成修改。

    具體而言,我們以 UIScrollView的 setContentOffset:animated 動畫為例。

    5.3setContentOffset:animated 動畫機(jī)制

    當(dāng)我們觸發(fā)[scrollView setContentOffset:CGPointMake(120,0) animated:YES]后,會觸發(fā)創(chuàng)建一個 UIScrollViewAnimation 的實例對象(UIAnimation的子類),接下來會調(diào)用 UIUpdateSequenceInsertItem 將這個動畫實例注冊到當(dāng)前的 UIUpdateCycle 循環(huán)中。

    UIUpdateCycle 負(fù)責(zé)根據(jù)設(shè)備的 CADisplay 屏幕刷新率和設(shè)置動態(tài)效果里設(shè)置的是否限制幀速率來抉擇出到底是以120hz還是60hz來驅(qū)動 UIUpdateCycle 循環(huán)的觸發(fā),當(dāng)以120hz觸發(fā)動畫循環(huán)時,接著會在每8ms間觸發(fā)一次_UIUpdateSequenceRun,來執(zhí)行 UIScrollViewAnimation 的動畫 progress 計算操作。

    如圖:

    每次觸發(fā)觸發(fā) _UIUpdateSequenceRun 時,會向 UIScrollViewAnimation 請求[UIAnimation fractionForTime:]來返回對應(yīng)時間戳的 contentOffset 和 progress,然后觸發(fā)修改 contentOffset,最終接近目標(biāo) contentOffset 后就完成了完整的動畫。

    5.4CAFrameRateRange

    當(dāng)我們設(shè)置 CAAnimation 的 preferredFrameRateRange 后,QuartzCore 會將 CAFrameRateRange 轉(zhuǎn)為CAFrameIntervalRange 結(jié)構(gòu),并最終嘗試觸發(fā) Render Server 在指定幀間隔內(nèi)渲染每一幀動畫。

    如下圖:

    5.5幀率變化探索

    所有的幀提交操作最終都是在 Render Server 觸發(fā)的,也就是只有從 Render Server 統(tǒng)計FPS才是最終的實際 FPS,那我們要怎么統(tǒng)計呢?

    QuartzCore 提供了一個系統(tǒng)級的面板工具,它可以很方便的顯示當(dāng)前的 QuartzCore 渲染信息,包括fps,frame duration等一應(yīng)俱全。

    我們可以在越獄后給 app 自簽名 com.apple.QuartzCore.debug 這個 entitlement 后,再調(diào)用如下代碼所示的私有 api 即可全局打開這個面板,可以方便的在手機(jī)端查看 Render Server 上的實際 FPS。

    extern"C"{

    intCARenderServerGetDebugOption(mach_port_t port, intkey);

    intCARenderServerGetDebugValue(mach_port_t port, intkey);

    voidCARenderServerSetDebugOption(mach_port_t port, intkey, intvalue);

    voidCARenderServerSetDebugValue(mach_port_t port, intkey, intvalue);

    }

    由于以上能力無法在非越獄設(shè)備上開啟,所以實際上我們無法檢測 app 在任意時刻的 FPS 變化情況。

    不過經(jīng)過分析,我們發(fā)現(xiàn)只要觸發(fā)了以下行為就可能代表要幀率要變化了。如下。

    1)在設(shè)置->動態(tài)效果里開啟或關(guān)閉“限制幀速率”:修改限制幀速率會觸發(fā)系統(tǒng)拋出 com.apple.CoreAnimation.CAWindowServer.DisplayChanged 的通知,QuartCore 會在啟動時注冊這個通知,并收到通知后通過 mach port 通信獲取當(dāng)前注冊的幀速率值,以動態(tài)修改 displaylink 的回調(diào)頻次。

    2)直接通過 opengl/metal api 提交一幀畫面給 Render Server。

    3)觸發(fā) CA::Transaction 對象的提交:除了觸發(fā)動畫提交,觸發(fā) view property 提交變更外,甚至創(chuàng)建 view 也會導(dǎo)致 source0觸發(fā)一次,如下圖所示。

    通過調(diào)試分析,我們大概清楚了 iOS15引入的 CAAnimation 的 preferredFrameRateRange 工作機(jī)制,如下圖所示。

    我們只要修改 UIUpdateSequenceRun 的回調(diào)頻率,也就是 -[UIAnimator _advanceAnimationsOnScreenWithIdentifier:withTimestamp:] 的回調(diào)頻次我們就能控制部分系統(tǒng)動畫的幀率,強(qiáng)制調(diào)節(jié)他的執(zhí)行頻次,或者我們通過模擬系統(tǒng)設(shè)置->動態(tài)效果->限制幀速率的實現(xiàn)方式,主動調(diào)用 -[CADisplay overrideMinimumFrameDuration:] 傳入4便可將 UIAnimator 的刷新率調(diào)節(jié)為 240/4=60hz,或者傳入8即可將系統(tǒng)動畫刷新率調(diào)節(jié)為 240/8=30hz。

    基于以上研究,理論上我們可以嘗試調(diào)用私有 api 來全局控制 CADisplay 的刷新率,來進(jìn)一步降低性能占用,但是由于 Render Server 是在其他進(jìn)程,我們還是無法控制 Render Server 的刷新率,并且私有 api 會導(dǎo)致 app 被拒審,所以我們最終依舊只能改造部分系統(tǒng)動畫實現(xiàn)以繼續(xù)基于 CAAnimation api 去優(yōu)化幀率。

    6、我們的優(yōu)化方案

    6.1概述

    從 iOS15開始蘋果新增加了 preferredFrameRateRange api 可用于設(shè)置相應(yīng)動畫或timer的刷新頻率,我們就可以基于該方案去改造相應(yīng)動畫即可。

    @propertyCAFrameRateRange preferredFrameRateRange

        API_AVAILABLE(macos(12.0), ios(15.0), watchos(8.0), tvos(15.0));

    但新的問題又來了,系統(tǒng)僅給 CAAnimation 和 CADisplayLink 的 api 提供了動態(tài)修改幀率的操作。

    但是在我們直播場景中,一共有如下幾種場景的動畫提交:

    • 1)UIView block 動畫;
    • 2)UIScrollView scroll 動畫;
    • 3)NSTimer 動畫;
    • 4)CAAnimation。

    除了4我們可以直接修改為 iOS15支持的 preferredFrameRateRange api 外,其它幾個我們要怎么解決呢?

    針對以上1~3點我們分別做如下處理。

    6.2UIView block 動畫

    通過分析 +[UIView animateWithDuration:delay : options:animations:completion:] 調(diào)用,我們發(fā)現(xiàn) animations block 里的 property animation 會被同步的創(chuàng)建為 CAAnimation 對象。

    如圖所示:

    那我們是否可以 hook CAAnimation 然后尋找時機(jī)設(shè)置它的 preferredFrameRateRange 以達(dá)到降幀的目的?

    很遺憾,不行,因為這個 api 觸發(fā)的動畫不會去觸發(fā)對應(yīng)的 setter 與 getter 去讀取新修改的值,而是被覆蓋為一個默認(rèn)值,導(dǎo)致無法降幀。

    再進(jìn)一步調(diào)試發(fā)現(xiàn)與UIViewPropertyAnimator 里是有主動 setPreferredFrameRateRange:的操作,那是否可以從這里入手?

    經(jīng)過驗證,果然可行,于是我們可以將所有的 UIView block animation 動畫都無縫替換為新方案后,即可實現(xiàn)自動降幀隨意靈活控制的目的了。

    部分代碼如下:

        if(@available(iOS 15.0, *)) {

            setFrameRateLevel(level);

            [UIViewPropertyAnimator runningPropertyAnimatorWithDuration:duration

                                                                  delay:delay

                                                                options:options

                                                             animations:animations

    completion:^(UIViewAnimatingPosition finalPosition) {

                                                                 if(completion) {

                                                                     completion(YES);

                                                                 }

                                                             }];

            clearFrameRateLevel();

        } else{

            if(level != MMAnimationFrameRateLevelNone) {

                if(level <= MMAnimationFrameRateLevelMedium)

                    options |= UIViewAnimationOptionPreferredFramesPerSecond30;

            }

            [selfanimateWithDuration:duration delay:delay options:options animations:animations completion:completion];

        }

    新的接口可以無縫替換原有的+[UIView animateWithDuration:delay : options:animations:completion:] 調(diào)用,可對所有系統(tǒng)實現(xiàn)降幀調(diào)節(jié)優(yōu)化,極大的方便了業(yè)務(wù)開發(fā)同學(xué)在不同場景中選擇合適的動畫幀率,以達(dá)到效果和耗電的平衡。

    6.3UIScrollView 動畫

    經(jīng)過上文的分析我們發(fā)現(xiàn) UIScrollView setContentOffset 的動畫是基于系統(tǒng)_UIUpdateTarget 機(jī)制來驅(qū)動的,由于對應(yīng)的回調(diào)是私有 api 觸發(fā)的,所以我們無法直接調(diào)節(jié)它的幀率,于是我們干脆自己實現(xiàn)一個基于 CADisplayLink 驅(qū)動的 setContentOffset 滑動動畫即可解決問題。

    即:創(chuàng)建一個CADisplayLink對象,指定我們需要的 preferredFrameRateRange 幀率,然后在每一幀回調(diào)時,根據(jù)當(dāng)前的時間戳計算出當(dāng)前需要設(shè)置的 contentOffset 值,直到最終達(dá)到了指定的動畫 duration 時間后,我們再把 contentOffset 調(diào)整為目標(biāo)值,即可。

    主體代碼大致如下:

    - (void)tt_contentOffset:(CGPoint)contentOffset duration:(CFTimeInterval)duration {

        self.duration = duration;

        self.deltaContentOffset = CGPointMinus(contentOffset, self.scrollView.contentOffset);

        if(!self.displayLink) {

            self.displayLink = [CADisplayLink displayLinkWithTarget:selfselector:@selector(updateContentOffset:)];

            if(@available(iOS 15.0, *)) {

                self.displayLink.preferredFrameRateRange = CAFrameRateRangeMake(15, 24, 0);

            } else{

                self.displayLink.preferredFramesPerSecond = 30;

            }

            [self.displayLink addToRunLoop:[NSRunLoopcurrentRunLoop] forMode:NSDefaultRunLoopMode];

        } else{

            self.displayLink.paused = NO;

        }

    }

    - (void)tt_onDisplayLink:(CADisplayLink *)displayLink {

        if(self.beginTime == 0.0) {

            self.beginTime = self.displayLink.timestamp;

            self.beginContentOffset = self.scrollView.contentOffset;

        } else{

            CFTimeInterval duration = displayLink.timestamp - self.beginTime;

            CGFloat percent = (CGFloat)(duration / self.duration);

            if(percent < 1.0) {

                CGFloat progress = (CGFloat)timingFunctionValue(self.timingFunction, percent);

                if(1 - progress < 0.001) {

                    [selftt_stopAnimation];

                } else{

                    [selftt_updateProgress:progress];

                }

            } else{

                [selftt_stopAnimation];

            }

        }

    }

    6.4NSTimer 動畫

    根據(jù)蘋果Explore UI animation hitches and the render loop 的說法,為了避免 vsync 信號和 timer  可能不同步的情形,我們直接用 CADisplayLink 來替換原先的 NSTimer,并在 CADisplayLink 回調(diào)里再觸發(fā)對應(yīng)的 UI 提交操作和動畫即可。

    這是因為:如下圖所示,對于13 pro max 高刷屏設(shè)備而言,其 UI 動畫的系統(tǒng)回調(diào)頻次是240hz,渲染幀率是可變的可為0~120fps 之間,而常規(guī)的 NSTimer 是基于 RunLoop 觸發(fā)回調(diào)的,RunLoop 的回調(diào)間隔可能只有幾十 us,那么 Timer 的靈敏度遠(yuǎn)高于 DisplayLink,所以完全是有可能在2幀渲染之間,回調(diào)了一次 Timer,而最終導(dǎo)致可能會多觸發(fā)了一幀的提交或一次渲染事件。所以我們采取 CADisplayLink 來替換 NSTimer,盡可能避免和 Display 不同步的渲染觸發(fā)操作。

    7、優(yōu)化后的效果

    按照蘋果的建議 ,app 內(nèi)容在沒有頻繁更新時,應(yīng)該盡量降低 FPS 以平衡功耗占用,因為高刷必然帶來更頻繁的 GPU 任務(wù)提交,使得 GPU 占用提升。

    并且 app 的刷新率是由所有內(nèi)容的最高刷新率決定的,也就是高 FPS 的界面元素會導(dǎo)致整個屏幕全局 FPS 提升,只有適當(dāng)平衡全局界面元素的 FPS 后,才能進(jìn)一步降低不必要的性能消耗。

    基于上述指導(dǎo)思想和優(yōu)化方案,我們最終在視頻號直播上驗證測試如下:

    先基于 「UIViewAnimationOptionPreferredFramesPerSecond30」 將直播點贊場景下的fps從高刷屏的120fps 降低到60fps,再基于 「UIViewPropertyAnimator」 將任意UIView block animation的幀率降低到30~48fps(最終全局穩(wěn)定在40~50fps),幀率同比下降16%而 GPU 同比下降了26%~38%(在主場景和其他場景)。并且由于我們的視頻畫面依舊是25fps的低幀率,所以此處降幀只是降低了 QuartzCore 的重復(fù)幀,而沒有減少任何畫面細(xì)節(jié),最終本質(zhì)上是無損的畫面降幀。

    另外,「在實驗過程中調(diào)試」,進(jìn)一步發(fā)現(xiàn)了一些很有用的環(huán)境變量,可以幫助我們更好的調(diào)試UI問題。

    如下:

    8、問題擴(kuò)展

    我們通過一些奇怪的繞過方式間接的實現(xiàn)了對所有基于 UIView block animation api 調(diào)用的動畫以及 CAAnimation api 調(diào)用的動畫都實現(xiàn)了動態(tài)降幀,這極大的改善了低幀率直播間的業(yè)務(wù)動畫導(dǎo)致的 GPU 功耗占用問題。

    那對于高幀率直播間我們還能怎么解決呢?

    基于蘋果的文檔幀率檔位設(shè)置建議和我們的綜合實踐效果,我們對高幀率直播間采取了部分用戶無明顯感知的有損降級策略。即當(dāng)檢測到設(shè)備過熱后,我們會將60fps 的直播流,以渲染端均勻丟幀的方式降幀到48fps。

    方案如下:

    最終也一樣取得了GPU 同比下降28%甚至更高的效果,有效減輕了過熱時的系統(tǒng)負(fù)載和功耗,并且從肉眼上基本無法分辨出差異。

    9、本文小結(jié)

    本文在不影響現(xiàn)有用戶體驗和業(yè)務(wù)邏輯的情況下,通過擴(kuò)展系統(tǒng)接口的能力與實驗調(diào)試分析,最終實現(xiàn)了一套 UI 動畫的幀率調(diào)節(jié)方案。

    該方案得到的效果是:

    • 1)快速改造既有業(yè)務(wù)的所有動畫,動態(tài)的控制各自的幀率;
    • 2)最終達(dá)到不影響效果的前提下,盡可能的降低了功耗;
    • 3)同時極大的減輕了業(yè)務(wù)開發(fā)同學(xué)適配多系統(tǒng)和改造動畫的工作量。

    該方案最終在微信視頻號直播上得到廣泛應(yīng)用,取得了較大的性能提升。

    至此,關(guān)于iOS視頻號直播的功耗優(yōu)化方案講解完畢。

    10、相關(guān)文章

    [1] 淘寶直播技術(shù)干貨:高清、低延時的實時視頻直播技術(shù)解密

    [2] 技術(shù)干貨:實時視頻直播首屏耗時400ms內(nèi)的優(yōu)化實踐

    [3] 七牛云技術(shù)分享:使用QUIC協(xié)議實現(xiàn)實時視頻直播0卡頓!

    [4] 首次披露:快手是如何做到百萬觀眾同場看直播仍能秒開且不卡頓的?

    [5] 淺談實時音視頻直播中直接影響用戶體驗的幾項關(guān)鍵技術(shù)指標(biāo)

    [6] 移動端實時視頻直播技術(shù)實踐:如何做到實時秒開、流暢不卡

    [7] 實現(xiàn)延遲低于500毫秒的1080P實時音視頻直播的實踐分享

    [8] 直播系統(tǒng)聊天技術(shù)(五):微信小游戲直播在Android端的跨進(jìn)程渲染推流實踐

    附錄:微信團(tuán)隊分享的其它文章

    微信團(tuán)隊分享:極致優(yōu)化,iOS版微信編譯速度3倍提升的實踐總結(jié)

    IM“掃一掃”功能很好做?看看微信“掃一掃識物”的完整技術(shù)實現(xiàn)

    微信團(tuán)隊分享:微信支付代碼重構(gòu)帶來的移動端軟件架構(gòu)上的思考

    IM開發(fā)寶典:史上最全,微信各種功能參數(shù)和邏輯規(guī)則資料匯總

    微信團(tuán)隊分享:微信直播聊天室單房間1500萬在線的消息架構(gòu)演進(jìn)之路

    企業(yè)微信的IM架構(gòu)設(shè)計揭秘:消息模型、萬人群、已讀回執(zhí)、消息撤回等

    IM全文檢索技術(shù)專題(四):微信iOS端的最新全文檢索技術(shù)優(yōu)化實踐

    微信團(tuán)隊分享:微信后臺在海量并發(fā)請求下是如何做到不崩潰的

    微信Windows端IM消息數(shù)據(jù)庫的優(yōu)化實踐:查詢慢、體積大、文件損壞等

    微信技術(shù)分享:揭秘微信后臺安全特征數(shù)據(jù)倉庫的架構(gòu)設(shè)計

    企業(yè)微信針對百萬級組織架構(gòu)的客戶端性能優(yōu)化實踐

    揭秘企業(yè)微信是如何支持超大規(guī)模IM組織架構(gòu)的——技術(shù)解讀四維關(guān)系鏈

    微信團(tuán)隊分享:詳解iOS版微信視頻號直播中因幀率異常導(dǎo)致的功耗問題


    (本文已同步發(fā)布于:http://www.52im.net/thread-4507-1-1.html



    作者:Jack Jiang (點擊作者姓名進(jìn)入Github)
    出處:http://www.52im.net/space-uid-1.html
    交流:歡迎加入即時通訊開發(fā)交流群 215891622
    討論:http://www.52im.net/
    Jack Jiang同時是【原創(chuàng)Java Swing外觀工程BeautyEye】【輕量級移動端即時通訊框架MobileIMSDK】的作者,可前往下載交流。
    本博文 歡迎轉(zhuǎn)載,轉(zhuǎn)載請注明出處(也可前往 我的52im.net 找到我)。


    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導(dǎo)航:
     
    Jack Jiang的 Mail: jb2011@163.com, 聯(lián)系QQ: 413980957, 微信: hellojackjiang
    主站蜘蛛池模板: 免费日本黄色网址| 亚洲大香伊人蕉在人依线| 免费国产小视频在线观看| 久久青草免费91观看| 亚洲国产精品嫩草影院| 久久久久久亚洲精品| 亚洲精品无码鲁网中文电影| 国产一精品一AV一免费孕妇| 美女视频黄的全免费视频网站| 四虎成年永久免费网站| 国产在线jyzzjyzz免费麻豆| 免费在线观看视频网站| 无人在线观看完整免费版视频| 岛国av无码免费无禁网站| 成人在线视频免费| 国产无遮挡裸体免费视频| 免费真实播放国产乱子伦| 亚洲高清成人一区二区三区 | 国产天堂亚洲精品| 最好2018中文免费视频| 一个人免费观看视频在线中文| 精品免费久久久久国产一区| 免费无码av片在线观看| 99re免费视频| 免费看美女裸露无档网站| 日韩免费观看的一级毛片| 日本三级2019在线观看免费| 最近中文字幕免费mv视频8| 国产成人无码a区在线观看视频免费 | 亚洲AV日韩精品久久久久久 | 国产91在线免费| 亚洲日本中文字幕一区二区三区| 亚洲精品V欧洲精品V日韩精品| 在线免费观看亚洲| 亚洲精华国产精华精华液网站| 一级成人生活片免费看| 三年片在线观看免费大全电影 | 野花香高清在线观看视频播放免费| 日韩精品久久久久久免费| 大学生一级毛片免费看| gogo全球高清大胆亚洲|