前言
引入weex提高了業(yè)務開發(fā)的效率以及靈活度,但是在使用過程中還是存在不少問題,其中內(nèi)存上就有很明顯的問題
一、weex頁面與原生頁面對比存在的內(nèi)存問題
1府寒、weex頁面內(nèi)存開銷過大
如圖進行頁面切換:
在進行到weex頁面的時候內(nèi)存暴漲。
2报腔、頁面Push跳轉(zhuǎn)堆棧內(nèi)存泄漏株搔。
從首頁Push跳轉(zhuǎn)到weex頁面,加載數(shù)據(jù)纯蛾,再返回纤房,重復多次得出下圖的結(jié)果:
而Push跳轉(zhuǎn)到原生頁面再返回,重復多次得出下圖內(nèi)存結(jié)果:
從上面兩張圖可以看出:原生頁面返回后從堆棧移除后會進內(nèi)存回收翻诉;而從weex頁面回到首頁炮姨,內(nèi)存沒有完全回收捌刮,存在一定的內(nèi)存泄漏,重復多次可以看到內(nèi)存相比較一開始會有明顯的增加舒岸。
3绅作、列表滑動的內(nèi)存情況
在沒有采用<list>和<cell>標簽的情況下:
weex頁面列表滑動內(nèi)存情況如圖:
通過趨勢圖列表滑動過程中內(nèi)存一直持續(xù)暴漲,沒有進行復用減少內(nèi)存開銷蛾派。
原生頁面列表滑動內(nèi)存情況如圖:
從圖中可以看到棚蓄,在滑動初始階段,內(nèi)存增長比較快碍脏,之后的滑動過程中對前面的控件進行復用,內(nèi)存開銷減少稍算,曲線變得平緩典尾,沒有出現(xiàn)內(nèi)存持續(xù)暴漲。
4糊探、 weex頁面內(nèi)存問題總結(jié):
1钾埂、weex頁面滑動沒有采用復用機制,導致內(nèi)存會跟著滑動持續(xù)暴漲
2科平、weex頁面占用內(nèi)存開銷過高褥紫,多個weex頁面可能導致APP因為內(nèi)存過大而Crash。
3瞪慧、weex頁面從堆棧移除內(nèi)存沒有完全回收髓考,存在一定的內(nèi)存泄漏。
二弃酌、內(nèi)存問題原因分析
1氨菇、滑動過程內(nèi)存持續(xù)暴漲問題
weex官方文檔上,建議使用高性能可復用<cell>
和<list>
妓湘,而【搜索頁】查蓉、【樂瘋搶】等weex頁面業(yè)務代碼中直接采用了<div>
和<scroller>
實現(xiàn)列表的布局,導致內(nèi)存問題的出現(xiàn)榜贴。
這里我們通過Weex源碼豌研,對四個標簽進行分析
可以在WXSDKEngine
中可以看出各個標簽對應的類:
<div> 對應WXComponent
<scroller>對應WXScrollerComponent
<cell>對應WXCellComponent
<list>對應WXListComponent
<div>
<div>
對應的WXComponent
相當于原生iOS控件的UIView,是所有視圖的基類唬党,一個普通的視圖沒有性能優(yōu)化鹃共、復用回收的機制。
<scroller>
<scroller>
對應的WXScrollerComponent
結(jié)構(gòu)如下:
并無相關(guān)復用回收的屬性初嘹,主要是提供一個可以滑動的容器及汉。
<cell>
查看<cell>
對應WXCellComponent
類的實現(xiàn)代碼可以發(fā)現(xiàn),WXCellComponent
相比較WXComponent
擁有復用回收的相關(guān)屬性isRecycle
<list>
<list>
對應的WXListComponent
的結(jié)構(gòu)如圖:
在成員列表中可以看到使用了iOS原生的UITableView屯烦,并且實現(xiàn)了使用了UITableView的代理方法坷随,實現(xiàn)了iOS的復用機制房铭,如圖:
同時WXListComponent
實現(xiàn)了WXCellComponent
中的代理方法,WXCellComponent
與WXListComponent
相關(guān)聯(lián)系温眉。
因此<list>
基于iOS的UITableView復用機制缸匪,實現(xiàn)高性能了可復用的列表容器。
結(jié)合<cell>
可以實現(xiàn)一個高性能的列表展示頁面类溢。
因此采用<list>
和<cell>
代替<scroller>
和<div>
解決滑動列表內(nèi)存暴漲的問題凌蔬。
2、weex頁面內(nèi)存開銷過高的問題
通過Instrument工具進行內(nèi)存分析闯冷,發(fā)現(xiàn)在進入weex 頁面時VM ImageIO_GIF_Data
和VM ImageIO
兩個對象內(nèi)存異常暴漲砂心。
VM ImageIO_GIF_Data 內(nèi)存增長情況:
VM ImageIO 內(nèi)存增長情況:
VM ImageIO_GIF_Data
由7.92M增長到16.55M,VM ImageIO
由0.11M增長到了1.02M,進入Weex頁面時蛇耀,這兩個對象總共增加了9.54M辩诞,而整個Weex頁面初始狀態(tài)占用內(nèi)存為15M左右(原生【商品詳情】頁:7M左右),占據(jù)了整個Weex頁面內(nèi)存的約60%纺涤。而在原生頁面中译暂,
VM ImageIO_GIF_Data
和VM ImageIO
對象幾乎沒有增長。而這兩個對象與
CoreGraphics
中進行圖片繪制撩炊、圖片渲染外永、圖片讀寫等相關(guān)方法有關(guān),而CoreGraphics為相對底層的模塊拧咳,相關(guān)方法比較消耗性能伯顶、內(nèi)存,并且容易產(chǎn)生內(nèi)存泄漏呛踊。初步可以判定砾淌,weex中大量調(diào)用了
CoreGraphics
中圖片處理的相關(guān)方法,導致了weex頁面內(nèi)存開銷過大谭网。
接著在WeexSDK的源碼中查找CoreGraphics
相關(guān)方法汪厨,定位問題。
在查找過程發(fā)現(xiàn)愉择,weex通過CoreGraphics繪圖方法將<text>等控件實例繪制成位圖進行顯示劫乱,以適應weex中的CSS布局。
在 WXComponent+Display
中锥涕,可以看到將控件繪制成圖片的代碼衷戈,并在layer
上顯示:
通過這部分的代碼可以定位到weex頁面內(nèi)存開銷過大的主要原因是: weex SDK 調(diào)用了CoreGraphics
方法將頁面中的<text>等控件繪制成圖片再布局顯示,占用了大量的內(nèi)存层坠。
weex的內(nèi)存泄漏也與大量調(diào)用了CoreGraphics
中方法有關(guān)殖妇。
通過Leaks工具定位到weex頁面內(nèi)存泄漏對象為CGDataProviderCreateWithCopyOfData
而
CGDataProviderCreateWithCopyOfData
為調(diào)用CoreGraphics
相關(guān)方法產(chǎn)生的對象。weex SDK調(diào)用
CoreGraphics
中的相關(guān)方法破花,但是沒有及時地釋放對象谦趣,導致了內(nèi)存泄漏疲吸。
weex SDK 大量CoreGraphics
方法將控件繪制成圖片再布局顯示,占用了大量的內(nèi)存前鹅,同時也導致了資源回收不及時的問題摘悴。
解決方案:
1、限制堆棧中weex頁面?zhèn)€數(shù):
天貓采用的也是該方案舰绘,通過控制頁面級數(shù)蹂喻,控制內(nèi)存,防止因為堆棧過多的weex頁面捂寿,內(nèi)存過大導致異常Crash口四。
2、頁面復用:
在打開weex頁面前秦陋,判斷堆棧中是否有該weex頁面窃祝,如果有便進行頁面復用,通過數(shù)據(jù)刷新頁面踱侣,同時通過調(diào)整堆棧將頁面顯示出來。