V8的内存限制
发布于 7 年前 作者 xudeming208 6872 次预览 最后一次回复是 7 年前 来自 问答
V8的内存限制
- V8把内存分为「新生代(New Space)」和 「老生代 (Old Space)」。新生代中的对象为存活时间较短的对象,老生代中的对象为存活时间较长或常驻内存的对象;–max_old_space_size改变的是老生代的内存大小,单位为M;–max_new_space_size改变的是新生代的内存大小,单位为K;
- 《深入浅出nodejs》书中“内存控制章节”说明,64位系统约为1.4GB,32位系统约为0.7GB;
- 书中说明,Buffer是基于c++,其内存是Node的C++层面提供的,不受V8内存限制;
- 我的测试结果:Buffer的内存不能大于2G,否则会内存泄漏,Array不能大于4G,这点我不太明白;为什么Buffer会有内存限制呢?而Array的限制却为4G,不应该是1.4G么?测试代码如下:
// 2G,会报错:RangeError: Invalid typed array length
new Buffer(2*1024*1024*1024)
// 2G-1,正常,不会报错
new Buffer(2*1024*1024*1024 - 1)
// 4G,会报错:RangeError: Invalid typed array length
new Array(4*1024*1024*1024)
// 4G-1,正常,不会报错
new Array(4*1024*1024*1024-1)
18 回复
其实都在文档里写着了 第一个 Buffer >= 2^31 抛错是 node 的一些限制:
require('buffer').constants可以看到:{ MAX_LENGTH: 2147483647, MAX_STRING_LENGTH: 268435440 },这个值也会变,64 位系统下限制是 2^31 -1,32 位系统下限制是 2^30 -1第二个 new Array >= 2^32 抛错的原因可以看这里:
另外,如果你在下面申请的 array 赋任意值就会因为申请内存超过 1.4G 导致 OOM 了,比如:
new Array(4*1024*1024*1024-1).fill('*')最后,目前更改 new space 的 falg 改为: --max_semi_space_size 了哦,new space 的值 = 2 * max_semi_space_size
参考:
@hyj1991 大神,请问new Array(4102410241024-1).fill(’’)给数组填充后为什么就会OOM呢,空的数组就不会呢,两者对内容的申请大小是不一样的吗?另外最后new space 的值 = 2 * max_semi_space_size是什么意思呀?谢谢
@xudeming208 只是 new Array 的话并没有实际地去申请内存,填充内容的时候才真的去申请内存并存储值了; new space 采用的是 scavenge 算法,这个算法是空间换时间的——new space 空间分为两个相等大小的 semi_space,同一时刻只有其中的一半在使用,所以你设置的 --max_semi_space_size 其实就是真正会使用到的大小,但是实际上真正的 new space 的大小 = 2 * max_semi_space_size
@hyj1991 new Array(parseInt(1024 * 1024 * 1024 * 1.4)).fill(’’)也会泄漏呢(node --max_semi_space_size=5000一样泄漏),通过查看知道直接new Array是只用了new space,资料说new space 64位系统为32M * 2,那为什么我new Array(1024 * 1024 * 32).fill(’’)也会泄漏呢?
@hyj1991 大神,我生产环境30多qps就显示cpugc飙高15~20多左右,看cpuprofile发现是monggose内部对象序列化的问题,我想请求在不修改代码的情况下,通过配置–max_semi_space_size或者old能不能降低cpu飙升情况?
@koroshi –max_semi_space_size或者old只是改变内存问题,cpu飙升是计算太多类的,这是两个问题吧
@xudeming208 我是想能不能通过提升默认内存减少gc次数提高计算问题?
@koroshi V8的old space用的是增量标记,gc应该不会太大占用CPU吧,而且,申请的内存越大,遍历gc的时候花的时间不是更长吗?不是更占CPU吗?请赐教,谢谢
@xudeming208 我刚开始看这块,我遇到的问题就是gc太高了,但是代码暂时还没法重构,就想查查有没有通过配置提高一点负荷,因为在机器cpu裱满的时候内存一直不吃紧,所以想有没有什么办法空间换时间提高一点性能,我有一点alinode那天的情况可以开个帖子请教请教
@koroshi 请教怎么查看gc太高了?
@xudeming208 我是alinode采集到的,不知道能否看看分析一下 https://cnodejs.org/topic/5ae036a3a86ec1f308ec250b
@xudeming208 接入性能平台看看呢 Node.js 性能平台 一般来说调整 max_semi_space_size 或者 max_old_space-size 是没办法优化 cpu 的序列化操作的
@hyj1991 方不方便帮忙看一下图表,是不是只能通过重构减少数据库查询优化了 https://cnodejs.org/topic/5ae036a3a86ec1f308ec250b
@hyj1991 好的,还麻烦大神帮忙赐教一下: new Array(parseInt(1024 * 1024 * 1024 * 1.4)).fill(’’)也会泄漏呢(node --max_semi_space_size=5000一样泄漏),资料说new space 64位系统为32M * 2,那为什么我new Array(1024 * 1024 * 32).fill(’’)也会泄漏呢?
非常感谢
@koroshi 看不懂 😓
@xudeming208 没人说过 new array 只会使用 new space 的空间啊。。。还有你把 semi space 设成这么大,你的进程就完蛋了。。。 你对内存泄漏的含义可能有误区,new 一个很大的 array 并不是泄漏,是你操作需要的内存超过了堆限制而已
@hyj1991 感谢大神 是的,semi space不能设置过大,我开始以为设置的是old space
@hyj1991
看这个log,老生代接近1.4G了,但是申请的Array大小只有32M,所以不可能是存储Array,导致的泄漏,这个报错是因为操作Array(fill)时需要的内存要超过1.4G了,所以报错的,我这样理解对吗?