閱讀222 返回首頁    go 阿裏雲 go 技術社區[雲棲]


手機淘寶性能優化

該文章來自於阿裏巴巴技術協會(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

  上一篇:go PostgreSQL 忘記提交2PC事務對數據庫造成的危害.
  下一篇:go 三年0故障總結,提升代碼質量的秘訣