手機淘寶性能優化
該文章來自於阿裏巴巴技術協會(ATA)精選文章。
手機淘寶性能優化
前言
為了滿足不同用戶的多樣性購物需求,過去兩年裏手淘的業務不斷膨脹,已經從單一的購物工具成為了購物內容平台。在手淘業務快速增長的同時,也帶來一些副作用,很多操作環節和頁麵因為承載功能太多,展示的速度變慢,用戶等待時間變長。性能優化勢在必行。
我們根據手機淘寶用戶的購物操作流程,對主鏈路進行了劃分,分為啟動,首頁加載,搜索,購物車,下單,支付環節,訂單查看等七個環節,每個步驟和模塊都做到監控,以量化數據為指導來進行優化。
下麵著重就啟動,首頁,購物車三個業務環節和網絡調優,圖片下載兩個基礎能力優化,優化使用的工具來介紹方案。
一.啟動優化
我們通過線下分析工具,線上灰度數據和代碼review,發現啟動慢主要有3個原因:1)引入了許多提前的初始化;2)在啟動階段主線程,存在耗時的非必要阻塞操作;3)部分主線程的鎖操作,導致主線程wait時間較多。
由此製定出優化的方案:
1)啟動無網+緩存
執行嚴格的無網策略,從用戶點擊圖標到首頁第一次展示整個過程沒有網絡交互,所有數據都是緩存或預置數據的方式來獲取。這是因為網絡IO耗時都比較長,通過將啟動階段的配置信息拉取和首頁運營數據的拉取等網絡IO後移,減少了時間開銷。
2)Task分級與異步化
我們將啟動中的所有task進行梳理和分級,根據級別來調整執行對應task的時機:
一級:block啟動的task,比如基礎sdk的初始化,首頁頁麵的創建等。
二級:可延遲到首頁加載成功後再執行的task,比如自動登錄,微淘狀態拉取,消息數拉取,配置信息拉取,運營數據拉取等操作 。
隻有一級task在啟動時執行,二級task延遲到啟動完成後串行執行,一級task必須沒有鎖操作,保證主線程不會被阻塞。
3)懶加載
優化之前在啟動過程中有很多業務的初始化操作,現在我們都采用懶加載策略,真正使用時再進行初始化加載,同時懶加載機製可以結合緩存或預置數據的方式來達到更好的效果。
比如在手淘的五個tab中,在沒有優化前,會在啟動時將五個tab對應的頁麵全部創建出來,而這五個頁麵中,隻有首頁是可見的,這些頁麵的創建都會有一定的耗時,而且除了創建以外,可能還會有一些業務邏輯在裏麵,比如發送一些請求等,那就會對整個啟動造成一定的性能損耗。所以在這次優化過程中,我們就使用lazy創建的方式進行優化,啟動隻創建可見的頁麵即首頁,而其它幾個頁麵,隻有在用戶點擊對應tab時,才進行創建顯示,這一個優化減少了近0.5s的耗時。
在上述三個主要策略的優化指導下,手淘的啟動流程圖變為如圖1所示的結構(Android情況也類似),從圖中可以看出,在主線程中,啟動階段我們隻保留了一些必要的初始化,其他一些非必要的操作都被懶加載或者異步化。通過這些策略的調整,我們達到了最開始設定的優化目標。
二.首頁優化
作為曝光量最高的頁麵,快速打開,穩定可用,及時更新是三大目標。
在首頁,展示的內容大致分為四類:
- 二級頁麵的入口,圖標,標題和位置相對固定;
- 頂部的輪播圖,一般為六幅圖片,作為不同運營模塊或活動的入口;
- 根據用戶身份運算出來的推薦商品,店鋪
- 頂部的消息盒子入口,帶未讀消息數字圖標。
對於這四類,采用不同的處理方式:
對於1和2,進行了大量的本地cache化工作,將這些入口文字圖標緩存在本地,首先展示上次cache內容,即使遇到無網的情況,首頁的整體框架頁麵,cache過的圖片和文字都能繪製出來。
本地cache內容會有一個有效時間戳,在繪製完畢後判斷如果cache實際過期了,就會異步網絡拉取,下載完畢後做頁麵刷新。
對於3)采用優化頁麵結構和層次的方法:推薦商品放在頁麵最下部,當用戶主動滾動上滑時做拉取繪製,避免頁麵一次拉取數據內容過度。
對於4)采用lazy化,即延遲處理,在首屏其他內容完成基礎繪製後,才調用接口拉取未讀消息數量。
同啟動步驟,首頁這裏也使用了任務異步化,目前主流手機都是多核處理器,部分 task 可以充分利用多核優勢,放在異步線程裏完成。比如首頁的數據量是相對比較大的,這些數據的加載,解析,拚裝都是非常耗時的操作,通過將這些耗時操作進行異步化,保證主線程的正常調度,隻有等數據都準備好了,才在主線程中進行UI的渲染更新,從而保障了主線程的流暢性。
三.購物車優化
購物車已經成為用戶的“第二收藏夾”,大量用戶通過多終端(PC,手機)不斷更新購物車的內容。在本地建立緩存保存數據,及時展示給用戶是提升打開購物車頁麵的必然手段。
但購物車中的商品會根據活動,店家,單一商品數量等產生不同的優惠組合,在端A上添加或刪除某一個商品,都會產生總價的複雜變化。而這個價格計算規則客戶端是無法實時獲取到的,由服務端計算完畢後下發。
所以這就導致購物車的價格展示不僅僅是一個簡單的“單品價格*商品數量=總價”的公式。客戶端在更新時,不斷要拉取到商品數量的變化,也要拉取到總價的變化。
以往是采用用戶主動刷新時全量更新的方法,現在優化為差量更新,不但流量減少,更有效地提升了拉取和刷新展示的速度。
上麵從業務環節講述了優化的方法,這裏從基礎服務角度來描述優化手段:
四.網絡優化
我們都知道主幹互聯網傳輸消耗的時間。主要包括三部分時間:DNS查找、TCP/TLS握手、數據傳輸。如何降低這三部分的耗時是網優的重要手段:
1)IP直連:
實現方式是HTTP DNS。在啟動完成後時發送一次HTTP請求獲取一組手機淘寶中使用的域名IP映射表,並緩存在本地。每次發起連接時,直接在網絡層使用IP代替域名直連。這種方式除了節省DNS時間,也可以規避掉公網DNS Server被攻擊導致的手淘服務癱瘓,這種情況2013年曾經發生過一次,手淘未受任何影響。
2)建立長連接:通過spdy實現, 減少TCP/TLS握手,降低建立連接成本。對於從CDN下載圖片速度幫助很大。
3) 域名收斂:收斂域名至公司的主力CDN域名。
盡量將請求集中在少數幾個域名下,以提高長連接的複用率.
4)TCP調優:
無線網絡特點是丟包率高、RT長,針對此特點可以針對性的TCP調優。
實施的方案:
調大初始擁塞控製窗口、關閉空閑slow-start、動態MSS、關閉TCP DF、去掉TCP時間戳
5)報文縮減:逐步由json協議格式向類PB協議轉換。
五.圖片方麵優化
圖片是電商app使用場景中最多的元素,如何快速節省流量的下載和渲染圖片是電商app都非常關注的。除了上麵網絡優化提的長連接,域名收斂等幾點之外,手淘還建立圖片的分級機製。
按分辨率,質量,銳化,格式四個緯度,對同一張圖片生成了不同組合的衍生文件。
設置了一係列匹配規則,針對不同屏幕,不同機型處理能力,不同網絡環境,配置出合適當前情況的圖片大小質量,保證圖片大小既節省又保證用戶視覺體驗。
其中一個經驗是當銳化程度高時,即使圖片質量較低,圖片色彩清晰度也都能讓用戶滿意。
六.工欲善其事必先利其器
在整個手淘的啟動優化過程中,係統的工具幫了我們很大的忙,Android的主要是自帶的 TraceView工具,IOS 主要是Instruments自帶的Time Profiler,System Trace等工具,它們都是數據采集和分析工具,主要用於分析應用程序中的hotspot,都非常強大。工具的具體使用方法不在本文論述範圍內,但是這些工具都提供了程序中的所有線程使用狀況,而且線程中的每一次的調用都可以看到具體的堆棧信息、耗時等詳細信息。通過對這些調用的分析,就可以找到啟動過程中相對耗時的調用。分析出具體的瓶頸點以後,就可以有針對性地進行具體優化了。
比如 手淘Android啟動階段以前有一個加密存儲的模塊,它會調用係統的SecretKeyFactory.getInstance()方法來生成加密的 key,我們是通過 TraceView 才發現這個函數調用會耗時300ms 以上,通過 TraceView看裏麵的調用堆棧發現它裏麵存在鎖操作,所以比較耗時,找到這個瓶頸點之後,手淘Android調研了多種加密存儲方式,最後換了一種比較輕量的加密存儲模塊,優化了該瓶頸點。
最後總結七大原則:
1.善用性能分析工具,建立監控體係
2.做好網絡基礎建設和網絡調優
3.離線化,本地緩存
4.懶加載
5.任務分級,合理並行
6.在主線程移除多餘操作
7.簡化合並複雜視圖
最後更新:2017-04-01 13:37:07