淘寶 Android 幀率采集分析與監(jiān)控詳解
APM 供給幀率的相關數(shù)據(jù),即 FPS(Frames Per Second) 數(shù)據(jù)。FPS 在必定程度上反映了頁面流通程度,但 APM 供給的 FPS 并不是很準確。恰逢手淘低端機功能優(yōu)化項目開啟,亟需相關方針來衡量對滑動體會的優(yōu)化,幀率數(shù)據(jù)探究實踐就此擺開。
在探究實踐中,咱們遇到了許多問題:
-
高刷手機占比相對不低,影響全體 FPS 數(shù)據(jù)
-
非人為滑動數(shù)據(jù)參雜在 FPS 中,不能直接表現(xiàn)用戶操作體會
-
核算均勻數(shù)據(jù)時,卡頓數(shù)據(jù)被淹沒在海量正常數(shù)據(jù)中,一次卡頓是否只影響一個 FPS 值仍是一次用戶操作體會?
經過一段時刻的探究,咱們沉積下來了一些方針,其間包括:滑動幀率、凍幀占比、scrollHitchRate、卡頓幀率。除了相關幀率方針之外,為了更好的指導功能優(yōu)化,APM 還供給了幀率主因剖析,一同為了更好的定位卡頓問題,也供給了卡頓倉庫。
下面是 APM 根據(jù)渠道的特性,對幀率相關探究實踐的詳細介紹,期望本文可以給咱們帶來一些協(xié)助。
體系烘托機制
在介紹方針的完成之前,首要需求了解體系是如何做烘托的,只要知曉體系烘托機制,才干協(xié)助咱們更好的進行幀率數(shù)據(jù)核算處理。
烘托機制是 Android 中重要的一部分,其間又牽扯甚廣,包括咱們常說的 measure/layout/draw 原理、卡頓、過度繪制等,都與其相關。在這兒咱們首要是對烘托流程進行全體了解,知曉后續(xù)需求核算哪幾部分、經過體系 API 得到了哪幾部分,以便核算出方針數(shù)據(jù)。
? 烘托流程
咱們都知道,當觸發(fā)烘托后,會走到 ViewRootImpl 的 scheduleTraversals。這時,scheduleTraversals 方法首要是向 Choreographer 注冊下一個 VSync 的回調。當下一個 VSync 來暫時,Choreographer 首要切到主線程(傳 VSync 上來的 native 代碼不運轉在主線程),當然它并不是直接給 Looper sendMessage,而是 msg.setAsynchronous(true) ,提高了 UI 的響應速率。
當切到主線程后,Choreographer 開端履行一切注冊了這個 VSync 的回調,回調類型分為以下四種:
- CALLBACK_INPUT,輸入事情
- CALLBACK_ANIMATION,動畫處理
- CALLBACK_TRAVERSAL,UI 分發(fā)
- CALLBACK_COMMIT
Choreographer 會將一切的回調按類型分類,用鏈表來組織,表頭存在一個巨細固定的數(shù)組中(因為只支撐這四種回調)。在 VSync 發(fā)送到主線程的音訊中,就會一條鏈表一條鏈表的取出順序履行并清空。
而在 scheduleTraversals 注冊的便是 CALLBACK_TRAVERSAL 類型的 callback,這個 callback 中履行的便是咱們最為熟悉的 ViewRootImpl#doTraversal() 方法,doTraversal 方法中調用了 performTraversals 方法,performTraversals 方法中最重要的便是調用了耳熟能詳?shù)? performMeasure、performLayout、performDraw 方法。
詳細代碼可以翻看: android.view.Choreographer 和 android.view.ViewRootImpl
從這兒咱們可以看到,想要上屏一幀數(shù)據(jù),至少包括:VSync 切到主線程的耗時、處理輸入事情的耗時、處理動畫的耗時、處理 UI 分發(fā)(measure、layout、draw)的耗時。
可是,當 draw 流程完畢,僅僅 CPU 核算部分完畢,接下來會把數(shù)據(jù)交給 RenderThread 來完成 GPU 部分作業(yè)。
? 屏幕改寫
Android 4.1 引進了 VSync 和三緩沖機制,VSync 給予開端 CPU 核算的機遇,以及 GPU 和 Display 交流的緩沖區(qū)的機遇,這樣有利于充分運用時刻來處理數(shù)據(jù)和削減 jank。
上圖中 A、B、C 分別代表著三個緩沖區(qū)。咱們可以看到 CPU、GPU、顯現(xiàn)器都能盡快拿到 buffer,削減不必要的等候。假如顯現(xiàn)器和 GPU 現(xiàn)在都運用著一個 buffer,假如下一次烘托開端了,因為還有一個 buffer 可以用于 CPU 數(shù)據(jù)的寫入,所以可以馬上開端下一幀數(shù)據(jù)的烘托,例如圖中第一個 VSync。
是不是引進三緩沖機制就沒有任何問題呢,當咱們仔細看上圖可發(fā)現(xiàn),數(shù)據(jù) A 在第三個 VSync 來暫時就現(xiàn)已準備好,隨時可以改寫到屏幕上,到實在刷到屏幕卻是第四個 VSync 降臨。由此可知,三緩沖盡管有效運用了等候 VSync 的時刻,削減了 jank,可是帶來了推遲。
這兒僅僅簡略帶咱們回顧了這塊的知識,建議咱們翻下發(fā)展的歷史,知其然亦要知其所以然。
對幀數(shù)據(jù)信息的挖掘
當咱們知道了整個體系烘托的流程后,咱們需求監(jiān)控什么,怎樣監(jiān)控,這是一個問題。
? 業(yè)界計劃
-
APM 原始計劃
當收到 Touch 事情后,APM 會收集頁面 1s 內 draw 的次數(shù)。這個計劃的長處是功能損耗低,可是存在致命缺點。假如頁面烘托總時長不足 1s 就停止改寫,會導致數(shù)據(jù)人為偏低。其次,觸碰屏幕不必定會帶來改寫,改寫也不必定是 Touch 事情帶來的。而以上狀況核算出來的都是臟數(shù)據(jù)。
可是,Android 在 ViewRootImpl 完成了一個Debug 的 FPS 計劃,原理與上訴計劃類似,都是在 draw 時累積時長到 1s,所以,假如是想要一個低本錢功能無損的線下測驗 FPS,這不失為一個計劃。
感興趣可以看 ViewRootImpl 的 trackFPS 方法。
-
Matrix
在幀率這部分,Matrix 立異性的 hook 了 Choreographer 的 CallbackQueue,一同還經過反射調用 addCallbackLocked 在每一個回調行列的頭部添加了自界說的 FrameCallback。假如回調了這個 Callback,那么這一幀的烘托也就開端了,當時在 Looper 中正在履行的音訊便是烘托的音訊。這樣除了監(jiān)控幀率外,還能監(jiān)控到當時幀的各個階段耗時數(shù)據(jù)。
除此之外,幀率回調和 Looper 的 Printer 結合運用,可以在呈現(xiàn)卡頓幀的時分去 dump 主線程信息,便于事務方處理卡頓,可是頻繁拼接字符串會帶來必定的功能開支(println 方法調用時有字符串拼接)。
-
常規(guī)
運用 Choreographer.FrameCallback 的 doFrame(frameTimeNanos: Long) 方法,在每一次的回調里核算兩幀之差,經過核算可以得到 FPS。
? 滑動幀率
FPS 是業(yè)界簡略而又通用的一個方針,是 Frames Per Second 的簡寫,即每秒烘托幀數(shù),淺顯來講便是每秒烘托的畫面數(shù)。
核算出 FPS 并不是咱們的方針,咱們一直期望核算出的是滑動幀率,針對 FPS,咱們更為關注的是用戶在交互進程中的幀率,監(jiān)控這一類幀率才干更好反映用戶體會。
首要,面臨之前的收集計劃,根本不能收集出契合界說的 FPS,所以原始的計劃就必須要進行舍棄,需求進行重新規(guī)劃。當看到 Matrix 的計劃時,覺得想法很棒,可是過分 hack,咱們更傾向于維護本錢更低、穩(wěn)定性高的體系開放 API。
所以,在挑選上,咱們仍是決議運用最一般的 Choreographer.FrameCallback 進行完成。當然,它不是最完美的,可是可以盡量在規(guī)劃上去避免這種缺點。
那咱們怎樣核算出一個 FPS 值呢?
Choreographer.FrameCallback 被回調時,doFrame 方法都帶上了一個時刻戳,核算與上一次回調的差值,就可以將之視之為一幀的時刻。當累加超越 1s 后,就可以核算出一個 FPS 值。
在這個進程中,有個點要咱們知曉,doFrame 在什么機遇回調:
首要,咱們每一次回調后,都需求對 Choreographer 進行 postFrameCallback 調用,而調用 postFrameCallback 便是鄙人一幀 CALLBACK_ANIMATION 類型的鏈表上進行添加一個節(jié)點。所以,doFrame 回調機遇并不是這一幀開端核算,也不是這一幀上屏,而是 CPU 處理動畫進程中的一個 callback。
當核算出一個 FPS 值后,就需求在上面疊加以下狀況了:
-
View 滑動幀率
在最開端完成時,View 只需滑動就監(jiān)控幀率,一直幀率產出到不滑動停止。根據(jù)需求,咱們的幀率收集就變成了如下這樣:
那怎樣監(jiān)控 View 是否有滑動呢?那就需求介紹一下這個 ViewTreeObserver.OnScrollChangedListener。畢竟只要了解完成原理,才干決議是否可用。
// ViewRootImpl#draw private void draw(boolean fullRedrawNeeded) { // ... if (mAttachInfo.mViewScrollChanged) { mAttachInfo.mViewScrollChanged = false; mAttachInfo.mTreeObserver.dispatchOnScrollChanged(); } // ... mAttachInfo.mTreeObserver.dispatchOnDraw(); // ... }
咱們可以看到,在 ViewRootImpl#draw 中,判斷了 mAttachInfo 信息中 View 是否發(fā)生了滑動,假如發(fā)生滑動就分發(fā)出來。那么什么時分設置的 View 位置變化(發(fā)生滑動)的呢?在 View 的 onScrollChanged 被調用的時分:
// View#onScrollChanged protected void onScrollChanged(int l, int t, int oldl, int oldt) { // ... final AttachInfo ai = mAttachInfo; if (ai != null) { ai.mViewScrollChanged = true; } // ... }
onScrollChanged 就直接連接著 View#scrollTo 和 View#scrollBy,在大多數(shù)場景下,現(xiàn)已滿足通用。
根據(jù)咱們之前講解的烘托流程:咱們可以看到 ViewTreeObserver.OnScrollChangedListener 的回調是在 ViewRootImpl#draw 中,那么 Choreographer.FrameCallback 的回調先于 ViewTreeObserver.OnScrollChangedListener 的。
關于單幀,就可以如下表示:
這樣,每一幀都帶上了是否滑動的狀況,當某一幀是滑動的幀,就可以開端計數(shù),一直累積時刻到 1s,一個滑動幀率數(shù)據(jù)核算出來就出來了。
-
手指滑動幀率
View 滑動幀率,在線下驗證時,與測驗渠道出的數(shù)據(jù)共同,并且可以契合基本需求,檢驗經過。上線后,也開端了運轉,并可以承擔起幀率相關作業(yè)。
可是,View 滾動并不代表著是用戶操作導致,數(shù)據(jù)一直不全是用戶體會的效果。所以,咱們開端完成手指的滑動幀率。
手指滑動幀率,首要咱們需求可以接納到手指的 Touch 行為。由于 APM 中已有對 Callback 的 dispatchTouchEvent 接口的 hook,所以決議直接運用此接口識別手指滑動。
這個時分,咱們需求知道幾個機遇問題:
-
有 dispatchTouchEvent 不會立馬發(fā)生 doFrame
-
經過 dispatchTouchEvent 核算移動時刻/距離超越 TapTimeout/ScaledTouchSlop,不必定立馬發(fā)生 doFrame
所以,經過 dispatchTouchEvent 核算移動時刻/距離超越 TapTimeout/ScaledTouchSlop 時,只會給一個 flag,告訴后邊的 ViewTreeObserver.OnScrollChangedListener 的 doFrame 可以開端核算成手指滑動幀率。
-
功能優(yōu)化/滑動次數(shù)識別
咱們在收到每一幀的 doFrame 回調后,都需求重新 postFrameCallback。每一次 postFrameCallback 都會注冊 VSync(假如沒有被注冊),當 Vsync 降臨后,會給主線程拋一個音訊,這勢必會給主線程帶來必定的壓力。
眾所周知,體系在頁面靜止的時分是不會進行烘托的,也就不會有 VSync 被注冊。那么在沒有烘托的時分,是否也需求 post 呢?不需求,沒有意義,是可以過濾掉的。根據(jù)這個理念,咱們對滑動幀率的核算進行了優(yōu)化。
需求削減非必要的幀回調與注冊,就需求清晰幾個問題:
-
起點(什么時分開端 postFrameCallback):在第一次收到 scroll 事情的時分(onSrollChanged)
-
結尾(什么時分不再 postFrameCallback):在核算完一個手指滑動 FPS 后,假如下一幀不再滑動,那么就停止注冊下一幀的回調。
假如細心的話,就會發(fā)現(xiàn),這兒的起點可以以為是手指帶來的滑動的烘托起點,這兒的結尾可以以為是手指帶來的滑動的烘托結尾(包括了 Fling),這個數(shù)據(jù)很重要,咱們相當于識別了一次手指滑動,并且可以供給每次手指滑動的耗時等數(shù)據(jù)。
這樣進行優(yōu)化是否就完美無缺呢?其實不是的,仔細看上圖的核算開端時刻點,就會發(fā)現(xiàn):損失了開端滑動的第一幀數(shù)據(jù)。因為咱們核算的是兩次 doFrame 回調的差值,即便知道當時這一幀是需求核算的幀,可是沒有上一幀的時刻戳,也就無法核算出開端滑動的這一幀實在的耗時。
? 凍動占比
凍幀是 Google 官方界說的一種幀:
Frozen frames are UI frames that take longer than 700ms to render.
凍幀作為一種特別的幀,不是被強烈建議不要呈現(xiàn)的幀,在華為等文檔中也被提及過。一旦呈現(xiàn)此類幀,頁面也就像凍住似的。所以,在 APM 中,也將這一類特別的幀納入監(jiān)控規(guī)模,核算出凍幀占比:
凍幀占比 = 滑動進程中的凍幀數(shù)量 / 滑動發(fā)生的幀數(shù)
? scrollHitchRate
scrollHitchRate 概念來自于 iOS,首要是用于描述滑動進程中,hitch 時長的占比。什么叫 hitch?可以簡略理解為單個幀耗時超越了烘托標準耗時的部分便是 hitch。
核算公式如圖所示:
這兒的分子是指整個滑動進程中,hitch 的累加值,這兒的分母便是整個滑動耗時(包括 Fling)。
咱們可能會問: 那為什么不必FPS? 不是可以用 fps 來檢測滑動卡頓狀況么,為什么還要有一個 Hitch rate ?
這是因為 FPS 并不適用于一切的狀況。比如當一個動畫中有停頓時刻, FPS 就無法反應該動畫的流通程度,并且并不是一切的運用都以達到 60 fps/120 fps 為方針,比如有些游戲只想以 30 fps 運轉。而關于 Hitch rate 而言,咱們的方針永遠是讓它達到 0。
引進 scrollHitchRate 單純?yōu)榱颂幚砀咚⑹謾C的數(shù)據(jù)紛歧致問題嗎?不是的。咱們在收集到一個 scrollHitchRate 數(shù)據(jù),還隱式的帶上了滑動次數(shù)。例如,在手淘場景下,主頁同學咨詢過一個問題,會不會頁面越往下刷,卡得越嚴峻?當收集到這個數(shù)據(jù)后,就可以進行回答了。
? 幀率主因剖析
無論是滑動幀率,仍是凍幀,更多的仍是傾向于監(jiān)控數(shù)據(jù),假如想要在數(shù)據(jù)上剖分出當時幀率低的首要原因仍是沒有方法入手的。
在之前烘托流程中,就講到烘托流程首要分紅哪幾步,假如可以將烘托流程的每一步都進行監(jiān)控,那么咱們就可以以為:當某一個異常幀呈現(xiàn)后,首要問題呈現(xiàn)在哪一個階段了,可是咱們仍是期望不要像 Matrix 那樣侵入體系代碼。根據(jù)這個思路,咱們發(fā)現(xiàn)體系供給了滿足咱們需求的 API:Window.OnFrameMetricsAvailableListener。Google Firebase 也同樣在運用這個 API 進行幀數(shù)據(jù)監(jiān)控,也不太會有后續(xù)的兼容性問題。
FrameMetrics,開發(fā)文檔見 https://developer.android.com/reference/android/view/FrameMetrics
在異步回調給的 FrameMetrics 數(shù)據(jù)中,會告訴咱們每一幀每一個階段的耗時,十分契合咱們的監(jiān)控訴求??墒侨匀挥袃蓚€問題值得注重:
- FrameMetrics API 是在 Android 24 上供給的,查看手淘用戶數(shù)據(jù)可以發(fā)現(xiàn),可以滿足基本需求;
- 一幀數(shù)據(jù)處理不及時會有丟數(shù)據(jù)的危險,但可以經過接口知曉丟掉了幾幀數(shù)據(jù)。
下面咱們就詳細查看下 FrameMetrics 數(shù)據(jù)中界說了哪些烘托階段:
FrameMetrics 參數(shù)常量 | 含義 |
UNKNOWN_DELAY_DURATION | 等候主線程耗時(VSync來了需求切換線程) |
INPUT_HANDLING_DURATION | 輸入事情處理耗時 |
ANIMATION_DURATION | 動畫處理耗時 |
LAYOUT_MEASURE_DURATION | layout & measure 耗時 |
DRAW_DURATION | draw耗時 |
SYNC_DURATION | sync耗時 |
COMMAND_ISSUE_DURATION | issue耗時 |
SWAP_BUFFERS_DURATION | 交流行列耗時 |
TOTAL_DURATION | 總耗時 |
摘錄自 Android 26。除上訴提及的字段此,還有幾個比較不錯的時刻戳字段,也可以探究出一些新奇的玩法,咱們可以一同探究下。
咱們有沒有發(fā)現(xiàn),跟烘托流程一模一樣。在盯梢了下相關源碼后,注冊一個 listener,并沒有太多的功能損耗,F(xiàn)rameMetrics 內部記載的時刻戳即便不注冊也會進行收集,所以不會帶來額外的功能開支。
首要咱們界說了一個需求進行剖析的幀耗時閾值,超越這個閾值就可以以為需求核算原因。咱們界說:當一幀某一個階段耗時超越閾值一半即為主因,反之則主因不存在。
如此一來,針對某一個 Activity 就可以剖分出是主線程卡頓導致幀率低,仍是布局問題導致 layout & measure 慢,亦或是 draw 有問題,在功能優(yōu)化時,直接鎖定主因進行優(yōu)化。
? 卡頓幀率
首要咱們再來回顧一下人眼的卡頓感知。原理上,高的幀率可以得到更流通、更逼真的動畫,要生成平滑連貫的動畫效果,幀速不能小于8FPS;每秒鐘幀數(shù)越多,所顯現(xiàn)的動畫就會越流通。一般來說人眼能繼續(xù)保存其印象1/24秒左右的圖像,所以一般電影的幀速為24FPS。相關于游戲而言,無論幀率有多高,60幀或120幀,最終一般人能分辯到的不會超越30幀。電影盡管只要24幀每秒,但由于每兩幀之間的距離均為1/24秒,所以人眼不不會感覺到顯著的卡頓,游戲或許咱們界面的改寫即便達到30幀每秒,但假如這一秒鐘內,30幀不是均勻分配,就算是每秒60幀,其間59幀都十分流通,而有一幀延時超越1/24秒,仍然會讓咱們感覺到顯著的卡頓。
這便是咱們界面上大部分狀況下都現(xiàn)已滑動的十分流通,可是偶然仍是會察覺到卡頓的原因。依照1/24秒的話,幀時刻在41.6ms,假如中間有超越41.6ms的話,咱們是可以感覺到卡頓的,假如依照1/30的話,幀時刻在33.3ms,假如某一幀的推遲時刻超越了33.3ms,那么人眼就容易察覺到這個進程,為了把這些卡頓的狀況反映出來,咱們需求在遇到這些幀的時分做一些記載??墒羌偃缭蹅儍H僅去記載進程中那些耗時超越33.3ms的幀,這種狀況下,一方面會丟失掉時刻的要素,很難去衡量卡頓的嚴峻性(畢竟一段時刻內不間斷的呈現(xiàn)卡頓,比偶然掉一幀要讓人顯著很多),另一方面,因為有多重緩沖區(qū)的影響,未必100%會掉幀,所以咱們僅僅取這個超越某一時刻的幀未必是準確的。
根據(jù)以上的考慮,這兒運用了一個瞬時FPS的概念用于衡量卡頓,瞬時FPS便是在滑動進程中發(fā)生的一些耗時比較小的區(qū)間中核算的值。例如用戶滑動了500ms,這個進程可能會呈現(xiàn)幾個用戶核算的瞬時FPS。這個進程是怎樣核算的?
- 滑動進程取得每一幀的時刻距離;
- 依照100(99.6ms,6幀的時刻)毫秒左右的時刻細化卡頓區(qū)間;
- 從時刻距離大于33.3毫秒的幀開端記載,作為區(qū)間起點;
- 完畢點是從起點開端的幀耗時相加,達到99.6ms并且后邊的一幀耗時小于17毫秒(或許抵達最終一幀),否則會繼續(xù)尋找完畢點;
- 這段時刻內在核算幀率,是這兒要尋找的卡頓幀率。
可以看到有3幀顯著超出比較多。依照以前的核算方法,幀耗時:1535ms, 幀數(shù)量是:83,那么這個界面的FPS是54。咱們可以看到幀率的FPS比較高,完全看不到卡頓了,即便前面有一些比較高的耗時幀,可是被后續(xù)耗時正常的幀給均勻掉了。所以以前的核算方法現(xiàn)已不能反映出這些卡頓問題。
依照新的核算方法,應該是從第7幀開端核算第一個瞬時FPS區(qū)間,從這一幀開端,核算至少99.6ms的時刻,那么69+16+15,現(xiàn)已達到了100ms,3幀,所以FPS是30,因為低于50,所以這一次FPS會比記載,其間最大的幀耗時是69ms。
第二次從17幀開端,5幀114ms,F(xiàn)PS為43ms,最大幀距離是61ms。
第三次從26幀開端,98+10=108ms,可是后邊幀的耗時時刻為19ms,超越16.6ms,所以仍然會加入一同核算。3幀,127ms,F(xiàn)PS為23。最大幀距離是98。
依照這次的核算,總共有3次卡頓FPS,分別是30,43,23,最大的幀耗時幀是98。
? 卡頓倉庫
假如運用主線程的 Looper Printer 來進行卡頓倉庫 dump,會因為大量的字符串拼接而帶來功能損耗。在 Android 10 上,Looper 中新增 Observer,可以功能無損的回調,但由于是 hide 的 API,則無法運用。最終的方法只能是不斷向主線程 post 音訊,可每隔一段時刻就給主線程拋音訊又會給主線程帶來壓力。
是否有更好的方法呢?有的,經過 Choreographer postFrameCallback,自身就會 post 主線程音訊,運用兩次回調之間的差值高于某一個閾值,就可以以為是卡頓。并且這個識別的卡頓,仍是滑動進程中的卡頓。
知道什么是卡頓,那什么時分 dump 呢?咱們運用了 watchdog 的機制 dump 出卡頓倉庫,即在子線程 post 一個 dump 主線程的音訊,假如單幀耗時超越閾值就進行 dump,假如在規(guī)則時刻內完成當時幀,就取消 dump 的音訊。當咱們收集上來倉庫后,咱們會將卡頓的倉庫進行聚類,便于更好的決議首要矛盾、告警處理。
對幀數(shù)據(jù)運用的探究
AB 與 APM 結合運用
上文首要仍是講解了咱們怎樣核算出一個方針、怎樣去排查問題,可是關于一個大盤方針而言,重之又重的當然是需求用來衡量優(yōu)化效果的,那怎樣去衡量優(yōu)化呢?最好的手段是 AB。APM 方針數(shù)據(jù)與 AB 測驗渠道打通,功能數(shù)據(jù)隨 APM 試驗產出。
這兒的AB渠道包括一休渠道、魔兔2渠道,一休渠道方針接入方法運用的是自界說方針,幀率僅僅作為方針之一接入,啟動、頁面等數(shù)據(jù)亦是其間之一。
一休是阿里集團一站式A/B試驗的服務渠道,向各個事務供給了可視化的操作界面、科學的數(shù)據(jù)剖析、自動化的試驗陳述等一站式的試驗流程;經過科學的試驗方法和實在的用戶行為來驗證最佳處理計劃,然后驅動事務增長。
咱們在進行頁面功能優(yōu)化時,可以直接運用相關方針對基準桶與優(yōu)化桶進行對比,直接而又顯著的顯現(xiàn)對頁面功能的優(yōu)化。
寫在最終
關于手淘功能監(jiān)控而言,幀率監(jiān)控、卡頓監(jiān)控僅僅功能監(jiān)控其間的一小環(huán),打磨好每一個細節(jié)也至關重要。相關數(shù)據(jù)除了與 AB 渠道搭配運用之外,現(xiàn)已與全鏈路排查數(shù)據(jù)、輿情數(shù)據(jù)、版別發(fā)布功能關口相打通,借用后臺聚類、告警、自動化郵件陳述等數(shù)據(jù)手段透出,專有數(shù)據(jù)渠道進行承接。關于數(shù)據(jù)的態(tài)度,咱們不僅是要有,并且要全面而強壯。
在一輪又一輪的技能迭代下,手淘的高可用表現(xiàn)也不斷完善與重構,期望在未來,手淘客戶端高可用相關數(shù)據(jù)可以更好的助力研制各個環(huán)節(jié),預防用戶體會腐化,協(xié)助不斷提升用戶體會。