React 16.8.6 版本存在內存泄露

發現這個React 內存泄露問題是某一天的晚上一直開着直播頁,直播頁用的 react 版本是 16.8.6,到了早上跳到這個頁面的時候,控制檯有點卡,懷疑是有內存泄露,因而就開始分析這個直播頁面。node

分析

打開控制檯 performance 面板點擊開始錄製,以下:react

從上圖能夠發如今這時間內, nodes 節點一直在增加,頗有可能發生了內存泄露。git

咱們來到 memory 面板分析內存變化:github

注:上圖的藍色線條表示在時間軸的最後該對象依舊存在,灰色線條則說明對象在時間軸內被分配,可是已經被gc(垃圾回收)了。數組

上圖都是點擊 gc 再進行記錄的,可是上圖還有不少藍色線條,並且內存一直往上漲,很明顯的內存泄露問題,那會是什麼致使內存泄露的呢?app

很快發現這裏有個 bi 的東西竟然佔了 31%的大小: dom

這個 bi 是用來幹嗎的?展開 bi ,鼠標懸浮在 bi 某處:3d

發現這個節點是直播間裏的進房消息,裏面是 react 存的 FiberNode 節點,觀察了一下里面這些 bi 基本上都是消息元素。code

選擇 summary,選出Detached (分離)的元素:orm

Detached HTMLDivElement 竟然有41429個,展開,鼠標懸浮:

仍是消息信息,說明是這個致使 bi 增長的。咱們繼續展開:

從上圖看 react 會保留消息的上下兄弟節點的引用,並且保留的引用層級有點深,各個節點嵌套依賴,致使一直存在內存裏:

仔細查下了項目消息相關代碼,發現並不會存在有內存泄露的操做。這裏簡單說下渲染消息的邏輯,消息有進房消息,聊天消息,禮物消息等等,消息展現會根據 messages 數組裏面的類型去渲染不一樣的消息。messages 數組不會無限增加,控制在 100 個,超過就刪掉第一個元素,保證維持100個元素渲染消息,可是從上圖來看,這些分離的元素並無被 react 徹底刪除,還保存在內存裏,查了下 React 的 Issue,並查了相關文章,發現有很多人遇到這個問題:

React 核心成員 Dan 給出的解決辦法是升級到 16.9.0。

這裏將項目 React 和 React-dom 版本升級16.9.0, 發現 FiberNode 節點仍是會一直增長。。。

繼續查看Issue 發現,React 版本 0.0.0-241c4467e 修復了這個問題。 Bug: Detached DOM node memory leak · Issue #18066 · facebook/react · GitHub

這個版本的 mr 已經合併在 React master 上 Null stateNode after unmount by bvaughn · Pull Request #17666 · facebook/react · GitHub

這個 mr 是 2019 年 12 月 20 號合併的,2019 年 12 月 20 號以後的版本是 16.13.0,這裏將項目直接升級到 16.13.1,而後查看 node 節點:

發現 node 節點能夠降下來了,查看 memory 面板:

對比Snapshot 5,分離的元素沒有新增,說明這個版本基本修復了這個問題。

結論

React 16.8.6 (16.2.5到16.12.0 可能會有,這些版本沒有驗證,可是 issue 裏面有人遇到)的版本會存在內存泄露問題,建議升級 React 到 16.13.0 以上。

相關文章
相關標籤/搜索