摘要:在前端項目端中,內(nèi)存泄露的定位往往比修復(fù)更加困難,即使瀏覽器有提供工具,但是面對成千上萬的元素和錯綜復(fù)雜的引用關(guān)系,開發(fā)則依然很難快速定位到問題代碼塊。
在前端項目(PC端)中,內(nèi)存泄露的定位往往比修復(fù)更加困難,即使google瀏覽器有提供Memory工具,但是面對成千上萬的元素和錯綜復(fù)雜的引用關(guān)系,開發(fā)則依然很難快速定位到問題代碼塊。
一、什么是內(nèi)存泄漏?
系統(tǒng)進(jìn)程不再用到的內(nèi)存,沒有及時釋放,就叫做內(nèi)存泄漏(memory leak)。當(dāng)內(nèi)存占用越來越高,輕則影響系統(tǒng)性能,重則導(dǎo)致進(jìn)程崩潰。Chrome限制了瀏覽器所能使用的內(nèi)存極限(64位為1.4GB,32位為1.0GB),這也就意味著瀏覽器將無法直接操作一些大內(nèi)存對象。
V8引擎在執(zhí)行垃圾回收時會阻塞 JavaScript應(yīng)用邏輯,直到垃圾回收結(jié)束再重新執(zhí)行JavaScript應(yīng)用邏輯,這種行為被稱為“全停頓”(stop-the-world)。 若V8的堆內(nèi)存為1.5GB,V8做一次小的垃圾回收需要50ms以上,造成假死現(xiàn)象。
二、JS內(nèi)存管理和垃圾回收機制GC
高級語言基本都有垃圾回收機制(garbage collection)自動管理內(nèi)存,降低程序員的負(fù)擔(dān),以達(dá)到解決內(nèi)存泄漏的目的,但是不允許人為手動觸發(fā),無法對內(nèi)存管理進(jìn)行任何干預(yù)。
老版本的瀏覽器使用引用計數(shù)法(Reference Counting)來管理內(nèi)存,即每次引用加一,被釋放時減一,當(dāng)這個值的引用次數(shù)變成 0 時,就可以將其內(nèi)存空間回收,缺點是循環(huán)引用時無法回收。
現(xiàn)代瀏覽器基本采用標(biāo)記清除法(Mark-and-Sweep)來管理內(nèi)存,即瀏覽器周期性地從某個根元素(譬如 window 對象)開始找引用變量,及這些變量引用的變量,這樣一直找下去。能找到的變量為可獲得變量,不能找到的將被內(nèi)存回收。
缺點是清除后內(nèi)存會產(chǎn)生很多細(xì)化的分塊,所以又衍生了標(biāo)記-整理法,不細(xì)講。
三、VUE中容易出現(xiàn)內(nèi)存泄露的幾種情況
內(nèi)存泄露是一個累積的過程,只有頁面生命周期略長的時候才暴露出問題,頻繁交互能夠加快累積的過程,偏展示的頁面很難把這樣的問題暴露出來(所謂刷新一下又能滿血復(fù)活)。所以很多時候我們都是被動式的等待問題暴露然后進(jìn)行排查的,主動式的分析通常比較難。vue頁面大多是單頁應(yīng)用,高交互且停留時間久,處理不好很容易出現(xiàn)內(nèi)存泄漏。本文章主要針對游離的dom對象進(jìn)行排查,普通的JS變量排查有時間再補充。
1.全局變量造成的內(nèi)存泄露
這里是首頁
按下Heap snapshots鍵,搜索Detached,發(fā)現(xiàn)沒有脫離文檔樹的dom元素,屬于正常現(xiàn)象
改變路由跳轉(zhuǎn)到other頁面,按下Heap snapshots鍵,搜索Detached,發(fā)現(xiàn)有兩處dom元素游離于當(dāng)前頁面之外,很明顯是window對象引用了home頁面中的div,即使此時home頁面已經(jīng)銷毀,home中的dom元素卻還駐留在內(nèi)存中無法釋放。
解決方案就是在頁面卸載的時候順便處理掉該引用。
這里是首頁
2.除了直接引用,window的原生方法也會起到引用dom元素使其無法釋放的效果。
這里是首頁
解決方法一樣,也是在頁面銷毀的時候,順便解除引用,釋放內(nèi)存
mounted () { window.addEventListener("resize", this.func) }, beforeDestroy () { window.removeEventListener("resize", this.func) }
3.一些全局的方法使用不當(dāng)也會造成內(nèi)存無法釋放,在頁面卸載的時候也可以考慮解除引用
這里是首頁
mounted () { this.$EventBus.$on("homeTask", res => this.func(res)) }, destroyed () { this.$EventBus.$off() }
造成游離dom節(jié)點的原因還有很多,不止這三種,總結(jié)起來:
1.window對象、事件總線、全局vuex上綁定了已銷毀頁面上的節(jié)點,到時節(jié)點不隨頁面一起銷毀
2.使用第三方庫創(chuàng)建實例,第三方庫一般會提供銷毀函數(shù),頁面跳轉(zhuǎn)時沒有調(diào)用正確的銷毀函數(shù)
3.有同學(xué)會說在頁面中使用閉包也會造成內(nèi)存泄露,在vue框架里有管理內(nèi)存的機制,只要按照它的正確編寫方法,理論上是不會造成內(nèi)存泄露的
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/54295.html
摘要:在前端項目端中,內(nèi)存泄露的定位往往比修復(fù)更加困難,即使瀏覽器有提供工具,但是面對成千上萬的元素和錯綜復(fù)雜的引用關(guān)系,開發(fā)則依然很難快速定位到問題代碼塊。 在前端項目(PC端)中,內(nèi)存泄露的定位往往比修復(fù)更加困難,即使google瀏覽器有提供Memory工具,但是面對成千上萬的元素和錯綜復(fù)雜的引用關(guān)系,開發(fā)則依然很難快速定位到問題代碼塊。 一、什么是內(nèi)存泄漏?系統(tǒng)進(jìn)程不再用到的內(nèi)存,沒有...
摘要:使用值來作路由。原生應(yīng)用本身就是多頁的場景,頁面間狀態(tài)的隔離比共享更重要一些。使用開發(fā)的是原生應(yīng)用,頁面棧的管理使用的也是原生的特性,沒有但是有模塊可以實現(xiàn)頁面的前進(jìn)和后退等操作。 系列文章的目錄在 ? 這里 (由于 我比較懶 最近一段時間在忙其他事,系列文章拖了好久終于又更新了。。。) 什么是 vue-router ? vue-router 官方文檔 vue-router 是針對 V...
閱讀 2958·2021-11-08 13:20
閱讀 1031·2021-09-22 15:20
閱讀 660·2019-08-30 15:53
閱讀 1964·2019-08-30 15:43
閱讀 1278·2019-08-29 17:21
閱讀 540·2019-08-29 12:15
閱讀 2375·2019-08-28 17:51
閱讀 3142·2019-08-26 13:26