高德車載導航的差分更新最佳化實踐

amap_tech發表於2020-03-24

導讀
隨著車載裝置聯網化,越來越多的車載裝置從離線走到了線上。高德車載導航也早已從過去的離線安裝包更新演進到了線上迭代更新。但原車載裝置的Android硬體配置遠低於手機,主要表現在處理器主頻低、記憶體和儲存空間有限,導致車載導航在車機上會出現無法下載新版本資料包、更新過程耗時長導致卡頓的情況,對導航應用的效能提出了要求。

為提高使用者體驗,高德技術團隊立項解決了該問題。本文小結了高德車載導航在版本自更新演進過程中二進位制差分解決方案的效能最佳化實踐。

差分更新方案比較

對於應用程式的版本更新迭代,除了分發全量的安裝包,還有一種更低成本的方式是分發增量包,即透過下發前後兩個版本的差異部分(這個過程下面簡稱Diff),然後在客戶端對原版本進行補丁更新(這個過程下面簡稱Patch)。因此也叫差分更新。

業內比較流行的差分方案主要有: bsdiff、Xdelta3和Courgette。最後一個方案Courgette來自於谷歌,主要解決的是可執行檔案的差分,而導航更新資源不僅包含可執行檔案,還包含了圖片等各種資原始檔。所以,我們主要對比bsdiff和Xdelta3方案。

bsdiff和Xdelta3方案比較

下面是我們對選取的幾個檔案做的bsdiff和Xdelta3差分效能對比:

bsdiff的優勢是壓縮比高,生成的差分檔案非常小,但Patch過程耗時。而Xdelta3的優勢是Patch過程耗時極短,但記憶體消耗非常大。

相比高德車載導航自身執行記憶體開銷不足100MB的情況,Xdelta3的Patch記憶體消耗無法接受。因此我們選用了bsdiff作為自更新方案。

原生bsdiff方案缺陷與改進

原生bsdiff方案使得壓縮比問題得到解決,但在車載導航自更新中還存在下面兩個缺陷:

  • 記憶體消耗大,整個過程會佔用10~35MB左右的記憶體。
  • 耗時長,整個包更新時間在3分鐘左右。

在對bsdiff的最佳化探索中我們發現Chromium開源專案中存在一份基於bsdiff的最佳化版本。該版本將bsidff的預設sufsort演算法替換成了divsufsort演算法,在Patch時間上有了較大的提升。

 

使用Chromium版本的bsdiff, 高德車載導航的自更新效能如下:

  • 記憶體消耗在10~20MB。
  • 整個Patch過程耗時仍然長達25秒左右。

耗時依然很長。

由於Patch過程是一個CPU密集型的操作,且車載裝置CPU的效能普遍不足,這意味著在整個升級過程中使用者能明顯感受到導航的操作卡頓。同時,更新時間越長意味著遭遇斷電的可能性也越大。

基於以上分析,我們決定對Chromium版本的bsdiff進行CPU和記憶體上的效能最佳化。

bsdiff在車載自更新業務中的效能最佳化實踐

在車載自更新業務上,我們設定的目標是整體更新時間小於6秒,且記憶體開銷小於2MB。整個最佳化的過程就是圍繞時間和空間的取捨。

記憶體最佳化方案

經過對bsdiff原始碼的分析,其Patch記憶體主要開銷來自檔案內容在記憶體中的讀寫暫存和Bzip2的解壓開銷。透過調整Bzip2引數可以降低部分記憶體,但無法達到期望。而檔案讀寫的記憶體佔用主要來自於其在記憶體中的暫存。

基於bsdiff差分Patch包的檔案格式,我們增加了滑動視窗緩衝區的Patch特性,使其在檔案的流式處理上能夠有更好的記憶體消耗可控性。每次讀取和寫入指定的滑動視窗大小資料,使資料即來即走。

演算法最佳化方案

經過上述的最佳化後,Patch過程的主要效能瓶頸在於Bzip2的解壓演算法中,即使調整Bzip2引數也無法減少本身的計算量。

bsdiff差分演算法的一個特性就是差分出的Patch資料包含了大量連續的01冗餘資料,而Bzip2演算法的優點就是對這類資料可以做到高度的壓縮,這也是bsdiff壓縮比高的原因。不過現在是目前的瓶頸。

此外,我們會製作軟體整體的壓縮差分包(即生成tar.bz2或zip格式檔案),也就是說針對每個Bzip2壓縮後的差分檔案還要再經過一次壓縮歸檔。這也意味著在客戶段要進行兩次的解壓。

替換壓縮演算法

類似的冗餘壓縮演算法有RLE(Run-length encoding),這個演算法也是Bzip2演算法的第一步。簡單來說RLE演算法就是針對連續多個冗餘位元組去掉其冗餘位元組,僅保留冗餘的長度資訊。這個演算法相對更簡單。

因此,我們將Bzip2壓縮演算法替換成了RLE演算法,實際結果發現生成的檔案很大, 壓縮比很低。但是可以透過再次壓縮歸檔製作一次差分包,就可以達到和Bzip2幾乎相同的壓縮比效果。唯一的不足就是在客戶端解壓後會佔用多一些磁碟空間, 而這個代價相對廉價多了。

最佳化效能對比

經過上述整體最佳化後,效能對比如下:

經過記憶體最佳化後的方案空間複雜度將為了O(1)。

上面的耗時差異在ARM車機會更明顯:

最終最佳化收益:記憶體消耗控制在2MB以內,整體Patch更新耗時3~5秒。

小結
透過對bsdiff的最佳化,高德車載導航在自更新效能上取得了較大收益。大幅縮短了使用者下載和更新時間,降低了對ARM車機的硬體資源要求。為推動車載導航OTA更新提供了技術基礎,對未來高德車載導航在分發新功能、新業務上鋪平了道路。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69941357/viewspace-2682156/,如需轉載,請註明出處,否則將追究法律責任。

相關文章