blog
blog copied to clipboard
M1 Air 运行 jest 时卡住 / 内存泄漏的问题解决方案
更新:后来发现问题出在 ts-jest 上面,把 ts-jest 换成 jest 自带的 babel-jest 就没有这个问题了。
前几天下单的 M1 Air 16GB 到手了,为了测试它到底能不能胜任平常的开发工作,我立刻就对它进行了一系列测试。
前几个小时都很顺利,但是在划词翻译项目里运行 jest
的时候遇到了问题。
划词翻译目前有 25 个 test 文件,我用 yarn 安装好依赖之后运行了 jest
,然后就出现问题了:
- 测试在运行到 7 of 25 的时候就卡住不动了
- CPU 直接飙到 100% 占用,16 GB 内存直接从剩余 8G 飙到剩余 54 MB。就这样持续运行一分钟后,电脑并没有变得卡顿,监测软件显示 CPU 温度有 101 度,不过用手摸主板只是有点点温热,没有明显升温)
- 2021 年 11 月 20 日更新:后来发现等待 8 分钟左右,测试是能正常跑完的。在这期间,CPU 和内存一直处于满负荷状态,也不知道会不会造成不好的影响
是内存不够用吗?但是我的 Windows 台式机也是 16 GB 一切正常。谷歌了一下,似乎是 jest / ts-jest 有内存泄漏的情况,相关的 issue 有:
- https://github.com/facebook/jest/issues/7874
- https://github.com/kulshekhar/ts-jest/issues/1967
这俩 issues 里有人提到在 jest.config.js 里加上如下配置就正常了:
{
globals: {
'ts-jest': {
isolatedModules: true
}
}
}
我试了一下,确实可以,但是加上这个之后,ts-jest 就无法识别 const enum
了,遇到就会报错,于是我想试试其它方案。
我开始尝试只运行一个 test 文件。虽然依然很慢,但 CPU 和内存占用都没有提升,过了大概 1 分钟不到吧,单个 test 运行通过了。
然后我尝试挨个运行这些测试文件,在大概运行了有 10 个左右的测试文件后,我再重新尝试直接运行 jest
,也就是同时运行全部 25 个 test 文件——但是这次居然顺利通过了,而且很快。
这么测试下来,我猜可能是从零开始构建 25 个测试文件以及相关的 ts 文件就会导致内存泄漏,于是我尝试运行 jest --clearcache
之后再重新运行 jest
,果然就重现了内存泄漏的问题,也就是又像开头那样,在 7 of 25 的时候卡住、CPU 和内存直接占满了。
总结
解决方案有两种:
- 加
isolatedModules: true
,但会导致无法识别const enum
且没有 type checking - 先挨个运行部分测试文件,越多越好,然后再一次性运行
jest
。运行一次就会构建好缓存了,以后再运行就不会出现这个问题了。
但是我记得我在 Windows 上清除缓存并运行 jest
是不会出现这个问题的。下次有机会的时候试试(但是有了 M1 我大概不会再用 Windows 写代码了 😂
2022 年 7 月 16 日更新:
今天还发现一种 jest 卡住的可能性,那就是组件写的有问题。今天卡住之后,我以为还是 jest 的内存泄漏引起的,但这次的情况跟内存泄漏的不太一样:内存并没有上涨,只有 CPU 温度飙到了 100 度。
比如下面这个测试:
/**
* @jest-environment jsdom
*/
import { render } from '@testing-library/react'
import { useEffect, useState } from 'react'
function TestCpt(props) {
const { items = [] } = props
const [inner, setInner] = useState([])
useEffect(() => {
setInner(items)
}, [items])
return <div>{items.length}</div>
}
test('测试 jest 卡住', () => {
render(<TestCpt />)
console.log('代码永远不会执行到这一行')
})
由于组件不传 items 参数的时候,每次都默认赋值了一个空数组,但是每次 render 时这个空数组都是一个全新的对象,这就导致 useEffect 在无限循环,从而导致 jest 卡住。
我之所以会发现这个问题,是因为我看到了这条回答 https://stackoverflow.com/a/70701097
然后按照它的说明,挨个取消注释掉代码,最后才确定问题是由一个无限循环的 useEffect 引起的。
前端开发内存占用很多吗, 如果跟 intel 的 16G 内存一样我觉得我 8G 都绰绰有余, 因为我的日常内存压力只有 30% 不到
我感觉 m1 的内存管理好像不太一样,我16g 只是开个一个项目都能占满 16g,但开三个项目也不觉得卡
恩, Mac都是这样的, 看内存压力就行了, 占多少不用在意