7

React 16.8.6 版本存在内存泄露

 3 years ago
source link: https://zhuanlan.zhihu.com/p/131367179
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

React 16.8.6 版本存在内存泄露

发现这个React 内存泄露问题是某一天的晚上一直开着直播页,直播页用的 react 版本是 16.8.6,到了早上跳到这个页面的时候,控制台有点卡,怀疑是有内存泄露,于是就开始分析这个直播页面。

分析

打开控制台 performance 面板点击开始录制,如下:

v2-d2a19da49b10fc755924caadb55a7e25_720w.jpg

从上图可以发现在这时间内, nodes 节点一直在增长,很有可能发生了内存泄露。

我们来到 memory 面板分析内存变化:

注:上图的蓝色线条表示在时间轴的最后该对象依旧存在,灰色线条则说明对象在时间轴内被分配,但是已经被gc(垃圾回收)了。

上图都是点击 gc 再进行记录的,但是上图还有很多蓝色线条,而且内存一直往上涨,很明显的内存泄露问题,那会是什么导致内存泄露的呢?

很快发现这里有个 bi 的东西居然占了 31%的大小:

这个 bi 是用来干嘛的?展开 bi ,鼠标悬浮在 bi 某处:

发现这个节点是直播间里的进房消息,里面是 react 存的 FiberNode 节点,观察了一下里面这些 bi 基本上都是消息元素。

选择 summary,选出Detached (分离)的元素:

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 以上。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK