前言
為了滿足不同用戶的多樣性購物需求,過去兩年里手機(jī)淘寶的業(yè)務(wù)不斷膨脹,已經(jīng)從單一的購物工具成為了購物內(nèi)容平臺。在業(yè)務(wù)快速增長的同時,也帶來一些副作用,很多操作環(huán)節(jié)和頁面因?yàn)槌休d功能太多,展示速度變慢,用戶等待時間變長,性能優(yōu)化勢在必行。
通過大半年的摸索總結(jié),從實(shí)踐中我們得出了App性能優(yōu)化的七大策略:
1.建立監(jiān)控體系,善用分析工具
2.完善網(wǎng)絡(luò)基礎(chǔ)建設(shè),不斷調(diào)優(yōu)
3.利用本地緩存,建立離線化
4.任務(wù)分級,合理并行,主線程移除多余操作
5.業(yè)務(wù)模塊懶加載
6.優(yōu)化頁面結(jié)構(gòu)和層次
7.做好圖片下載緩存工作
首先是監(jiān)控體系的建立:根據(jù)手機(jī)淘寶用戶的操作習(xí)慣,我們對購物主要鏈路進(jìn)行了劃分,分為啟動,首頁,搜索,購物車,下單,支付環(huán)節(jié),訂單查看等七個環(huán)節(jié),每個步驟和模塊都做到監(jiān)控,以量化數(shù)據(jù)為指導(dǎo),有的放矢進(jìn)行優(yōu)化。
對于手機(jī)淘寶購物主要鏈路的七個業(yè)務(wù)環(huán)節(jié),本文將抽取三個做重點(diǎn)介紹:啟動、首頁、購物車;然后針對網(wǎng)絡(luò)調(diào)優(yōu),圖片下載緩存兩個基礎(chǔ)能力的優(yōu)化和如何善用分析工具來做詳細(xì)介紹。
一.啟動優(yōu)化
通過線下分析工具,線上灰度數(shù)據(jù)和代碼review,發(fā)現(xiàn)啟動慢主要有三個原因:
提前引入了許多模塊的初始化;
在主線程,存在耗時的非必要阻塞操作;
部分鎖操作,導(dǎo)致主線程wait時間較長。
由此制定出優(yōu)化的方案:
1)采用優(yōu)化策略3--利用本地緩存,建立離線化
從用戶點(diǎn)擊圖標(biāo)到首頁第一次展示,整個過程執(zhí)行嚴(yán)格的無網(wǎng)策略,不做任何網(wǎng)絡(luò)交互,所有數(shù)據(jù)通過緩存或預(yù)置的方式獲取。
通過將耗時的網(wǎng)絡(luò)IO操作后移,減少了時間開銷。
2)采用優(yōu)化策略4--任務(wù)分級,合理并行
將啟動中的所有任務(wù)進(jìn)行梳理和分級,根據(jù)級別來調(diào)整執(zhí)行對應(yīng)任務(wù)的時機(jī):
一級:阻塞啟動的任務(wù),比如基礎(chǔ)SDK的初始化,首頁頁面的創(chuàng)建等。
二級:可延遲到首頁加載成功后再執(zhí)行的任務(wù),比如自動登錄,配置信息和運(yùn)營數(shù)據(jù)拉取等。
啟動時只執(zhí)行一級任務(wù),二級任務(wù)延遲到啟動完成后串行執(zhí)行,一級任務(wù)必須沒有鎖操作,保證主線程不會被阻塞。
3)采用優(yōu)化策略5--懶加載
優(yōu)化前,啟動過程存在很多業(yè)務(wù)的初始化操作;優(yōu)化后,采用懶加載策略,真正使用時才進(jìn)行初始化加載,同時懶加載機(jī)制可以結(jié)合緩存或預(yù)置數(shù)據(jù)的方式來達(dá)到更好的效果。
比如在手機(jī)淘寶的五個TAB中,優(yōu)化前,啟動時會將五個TAB對應(yīng)的頁面全部創(chuàng)建出來,而實(shí)際上只有首頁可見,其他頁面的創(chuàng)建,包括頁面中業(yè)務(wù)邏輯的請求發(fā)送,都會對整個啟動造成性能損耗。使用懶加載的方式優(yōu)化后,啟動只創(chuàng)建可見頁面即首頁,其它頁面只在用戶點(diǎn)擊對應(yīng)TAB時才進(jìn)行創(chuàng)建顯示,此優(yōu)化一舉減少了近0.5秒的耗時。
在上述三個主要策略的優(yōu)化指導(dǎo)下,手機(jī)淘寶的啟動流程圖調(diào)整為如圖1所示,主線程中啟動階段只保留了必要的初始化,其他非必要的操作都被懶加載或者異步化。
二.首頁優(yōu)化
作為曝光量最高的頁面,快速打開,穩(wěn)定可用,及時更新是三大目標(biāo)。
在首頁,展示的內(nèi)容大致分為四類:
二級頁面的入口,圖標(biāo),標(biāo)題和位置相對固定;
頂部的輪播圖,作為不同運(yùn)營模塊或活動的入口;
根據(jù)用戶身份運(yùn)算出來的推薦商品,店鋪
頂部的消息盒子入口,帶未讀消息數(shù)字圖標(biāo)。
不同的內(nèi)容采用不同的處理策略:
對于第1,2類內(nèi)容,采用策略3,即進(jìn)行本地cache化工作,將入口文字圖標(biāo)緩存在本地。渲染時優(yōu)先展示上次cache內(nèi)容,即使遇到無網(wǎng)的情況,首頁的整體框架頁面和cache過的圖片和文字都能繪制出來。
本地cache通過時間戳來保證版本內(nèi)容的及時更新。
在今年雙十二的活動中,手機(jī)淘寶率先推出了圖標(biāo)運(yùn)營,通過更新云端上的配置,待客戶端上前一次cache過期就自然過渡到此版本,給用戶帶來了驚喜。
對于第3類內(nèi)容,采用策略6,優(yōu)化頁面結(jié)構(gòu)和層次:推薦商品放在頁面最下部,默認(rèn)不顯示,當(dāng)用戶滾動上滑時做拉取繪制,避免頁面一次拉取數(shù)據(jù)內(nèi)容過多。
對于第4類內(nèi)容則采用策略5,即懶加載,在首屏其他內(nèi)容完成基礎(chǔ)繪制后,才調(diào)用接口拉取未讀消息數(shù)量。
此外,首頁數(shù)據(jù)量相對較大,這些數(shù)據(jù)的加載,解析,拼裝都是非常耗時的,而目前主流手機(jī)都是多核處理器,可以充分利用多核優(yōu)勢,將這些耗時操作放在異步線程里完成,保證主線程正常調(diào)度。當(dāng)數(shù)據(jù)準(zhǔn)備完畢,才在主線程中進(jìn)行UI的渲染更新,從而保障了主線程的流暢性。
三.購物車優(yōu)化
購物車已經(jīng)成為用戶的“第二收藏夾”,用戶通過多終端(PC,手機(jī))不斷更新購物車的內(nèi)容。在本地建立緩存保存數(shù)據(jù),及時展示給用戶是提升打開購物車頁面的必然手段。
但由于優(yōu)惠規(guī)則和總價計算必須在服務(wù)端完成,客戶端在更新購物車時,不但要拉取商品數(shù)量的變化,也要拉取總價的變化。
以往是采用主動刷新時全量更新的簡單方法,現(xiàn)在優(yōu)化為差量更新,不但流量減少,更有效地提升了拉取和刷新展示的速度。
四.網(wǎng)絡(luò)優(yōu)化
上面從三個業(yè)務(wù)環(huán)節(jié)講述了優(yōu)化策略,現(xiàn)在從基礎(chǔ)服務(wù)角度來描述優(yōu)化手段。主干互聯(lián)網(wǎng)傳輸消耗的時間,主要包括三部分:DNS查找、TCP/TLS握手、數(shù)據(jù)傳輸。如何降低這三部分的耗時是網(wǎng)優(yōu)的重要手段:
IP直連:
自行實(shí)現(xiàn)承載在HTTP協(xié)議上的DNS解析協(xié)議。能節(jié)省DNS查找時間,規(guī)避傳統(tǒng)DNS可能存在的劫持問題。2013年業(yè)界曾經(jīng)發(fā)生過一次公網(wǎng)DNS Server被攻擊,手機(jī)淘寶未受任何影響。
建立長連接:
通過SPDY實(shí)現(xiàn),減少TCP/TLS握手,降低建立連接成本。對于從CDN下載圖片速度幫助很大。
域名收斂:
收斂域名至公司的主力CDN域名。將請求集中在少數(shù)幾個域名下,以提高長連接的復(fù)用率.
TCP調(diào)優(yōu):
無線網(wǎng)絡(luò)特點(diǎn)是丟包率高、RT長,針對此特點(diǎn)可以做針對性的TCP調(diào)優(yōu)。
報文縮減:
逐步由JSON協(xié)議向類PB協(xié)議轉(zhuǎn)換。
五.圖片方面優(yōu)化
圖片是電商App使用場景中最多的元素,如何節(jié)省流量,快速渲染是電商App都非常關(guān)注的。
在建立長連接,域名收斂等網(wǎng)絡(luò)優(yōu)化之外,手機(jī)淘寶還建立圖片的分級機(jī)制:按分辨率,質(zhì)量,銳化,格式四個緯度,對同一張圖片生成了不同組合的衍生文件。
設(shè)置了一系列匹配規(guī)則,針對不同的屏幕,機(jī)型,處理能力和網(wǎng)絡(luò)環(huán)境,配置出合適的圖片大小質(zhì)量,保證圖片既節(jié)省流量又滿足用戶視覺體驗(yàn)。
其中一個經(jīng)驗(yàn)是當(dāng)銳化程度高時,即使圖片質(zhì)量較低,圖片色彩清晰度也都能讓用戶滿意。
其中一個經(jīng)驗(yàn)是當(dāng)銳化程度高時,即使圖片質(zhì)量較低,圖片色彩清晰度也都能讓用戶滿意。
六.工欲善其事必先利其器
在整個手淘的啟動優(yōu)化過程中,系統(tǒng)的工具幫了我們很大的忙,Android的主要是自帶的 TraceView工具,IOS 主要是Instruments自帶的Time Profiler,System Trace等工具,它們都是數(shù)據(jù)采集和分析工具,主要用于分析應(yīng)用程序中的hotspot,都非常強(qiáng)大。工具的具體使用方法不在本文論述范圍內(nèi),但是這些工具都提供了程序中的所有線程使用狀況,而且線程中的每一次的調(diào)用都可以看到具體的堆棧信息、耗時等詳細(xì)信息。通過對這些調(diào)用的分析,就可以找到啟動過程中相對耗時的調(diào)用。分析出具體的瓶頸點(diǎn)以后,就可以有針對性地進(jìn)行具體優(yōu)化了。
比如 手淘Android啟動階段以前有一個加密存儲的模塊,它會調(diào)用系統(tǒng)的SecretKeyFactory.getInstance()方法來生成加密的 key,我們是通過 TraceView 才發(fā)現(xiàn)這個函數(shù)調(diào)用會耗時300ms 以上,通過 TraceView看里面的調(diào)用堆棧發(fā)現(xiàn)它里面存在鎖操作,所以比較耗時,找到這個瓶頸點(diǎn)之后,手淘Android調(diào)研了多種加密存儲方式,最后換了一種比較輕量的加密存儲模塊,優(yōu)化了該瓶頸點(diǎn)。
最后總結(jié)七大原則:
1.善用性能分析工具,建立監(jiān)控體系
2.做好網(wǎng)絡(luò)基礎(chǔ)建設(shè)和網(wǎng)絡(luò)調(diào)優(yōu)
3.離線化,本地緩存
4.懶加載
5.任務(wù)分級,合理并行
6.在主線程移除多余操作
7.簡化合并復(fù)雜視圖
關(guān)于Java和Android大牛頻道
Java和Android大牛頻道是一個數(shù)萬人關(guān)注的探討Java和Android開發(fā)的公眾號,分享最有價值的干貨文章,讓你成為這方面的大牛!