在咱們的項目中有一個可視化配置的模塊,是經過go.js生成canvas來實現的。可是,咱們發現這個模塊在瀏覽器中常常會引發該tab頁崩潰。開啓chrome的任務管理器一看,進入該頁面內存和cpu就會暴漲,內存常常會飆到700多M。可是咱們的canvas實際的像素只有約500x500,根據一些粗略的計算,大概只佔了1M的內存,這個計算過程可參考100*100的 canvas 佔多少內存。那麼咱們這700M內存是哪裏來的呢?javascript
咱們可使用chrome開發者工具來分析咱們的調用棧。這邊我是先經過Performance來幫助咱們定位問題,它會幫咱們生成一段過程當中一些數據的變化,包括js堆內存、dom節點數量、動畫幀等數據,如圖:vue
這是切換至一個canvas畫布較大的一個模塊的performance分析表現,能夠看到佔用了472M的內存。下面折線圖藍色部分是js堆內存的變化,而Main下面黃色與紫色的矩形框就是咱們的調用棧,上下兩部分是按照時間一一對應的。能夠看到,藍色的折線呈高低起伏的態勢,GC回收以後低點基本和高點持平,所以能夠判定幾乎不存在內存泄漏的問題。而後咱們能夠放大去看一看,內存升高的時候,js作了些什麼事情,找一找規律。java
咱們隨機找一段內存增加的區域,能夠看到在內存增加的過程當中,最爲頻繁調用的就是Observer相關的代碼。可是就這麼看,咱們不可以明白Observer是在幹什麼。此時咱們能夠借用Memory選項中的Allocation Sampling按照javascript function來查看內存分配,咱們一樣錄製以上的一段操做。chrome
此時咱們可以清楚的看到,的確是這個Observer在做怪。同時,咱們能夠看到這是vue的代碼,點擊右邊的文件查看source code,就能夠清楚的明白這就是vue在執行依賴收集的操做,此時會給屬性添加watcher。那咱們這裏爲何會有如此多的屬性被添加了watcher呢?看了一下代碼,原來是我把go.js的一個實例掛到了vue的data選項中,放到data中的屬性會被vue執行依賴收集的相關操做,而這個實例擁有很是多的嵌套屬性,所有都會被添加watcher。其實,咱們只是想單純的存儲一下這個實例,供咱們後續調用其相關的方法,添加watcher對咱們來講徹底沒有意義,那咱們如何避免這樣的問題呢?canvas
上網搜索了相關的解決方案,大概有以下幾種:瀏覽器
javascript data() { return { $goDiagram: null } }
可是這樣聲明,在template中引用時會報找不到$goDiagram屬性的錯誤,具體的緣由我還沒深究,有空能夠研究一下。export default { goDiagram: null, mounted() { this.$options.goDiagram = xxx } }
這應該是比較好的一個方法,vue官方中也說明了$options用來包含自定義屬性,例如咱們平時引入的常量或是枚舉類型,咱們也不但願它們被添加無心義的watcher,所以能夠經過這種方式來定義,在template中引用時只須要{{$options.xxx}}便可。這種方式惟一的缺點就是不能像data那樣一眼望去就能清楚地知道你定義了什麼屬性。
項目中我採用了第一種方式,通過修改後內存佔用量減小到原來的1/5到1/6,能夠說效果很是好,不再會出現瀏覽器崩潰的狀況了。dom
經過這樣的一個問題,咱們主要可以學習到兩點:工具