「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战」。
本文将知道:
- Node中通过Javascript使用内存是多少?
- Node内存限制的主要原因是什么?
- Node会有内存限制的深层原因什么?
- Node的内存限制怎么打开?
我们在学习JavaScript编程时听说过,它与Java一样,由垃圾回收机制来进行自动内存管理这使得开发者不需要像C/C++程序员那样在编写代码的过程中时刻关注内存的分配和释放问题。
但在浏览器中进行开发时,几乎很少有人能遇到垃圾回收对应用程序构成性能影响的情况。
Node极大地拓宽了JavaScript的应用场景,当主流应用场景从客户端延伸到服务器端之后,我们就能发现,对于性能敏感的服务器端程序,内存管理的好坏、垃圾回收状况是否优良,都会对服务构成影响。而在Node中,这一切都与Node的JavaScript执行引擎V8息息相关。
Node中通过Javascript使用内存限制
在一般后端开发语言中,在基本的内存使用上没有什么限制,然而在Node中通过Javascript使用内存是就会发现只能使用部分内存
- 64位系统下约 1.4GB
- 32位系统下约 0.7GB
在这样的限制下,将会导致Node 无法直接操作大内存对象,这样在单个Node 进程的情况下,计算机的内存资源将无法得到充足的使用。
V8限制内存的主要原因
在于Node基于V8的构建,所以在Node中使用的Javascript对象基本上都是通过V8自己的方式来进行分配和管理的。
V8的这套内存管理机制在浏览器的应用场景下使用起来绰绰有余,足以胜任前端页面的所有需求,但在Node中,却限制了开发这个随心使用大内存的想法。
如果实际应用中不小心触碰了这个界限,会造成进程退出。
要知道V8为何限制内存的用量,需要回归到V8在内存使用的策略上。
V8的对象分配
在V8中,所有的js对象都是通过堆来进行分配的。
Node提供查看V8内存使用量的查看方式:
$ node
> process.memoryUsage();
{ rss: 28872704,
heapTotal: 10207232,
heapUsed: 5796856,
external: 8798 }
memoryUsage(); 返回的三个属性中
| 标题 | |
|---|---|
| heapTotal | 申请到的堆内存 |
| heapUsed | 当前使用量 |
V8的堆示意图
当代码上中声明的变量并赋值时,所使用的对象的内存就分配在堆中。
如果申请的堆空闲内存不够分配新的对象,将继续申请堆内存,知道堆的大小超过V8的限制为止。
V8限制堆大小的深层原因
1. 表层原因
V8最初为浏览器而设计,不太可能遇到用大量内存的场景。
对于网页来说,V8的限制值已经绰绰有余。
2. 深层原因
V8的垃圾回收机制的限制。
按官方的说法,以1.5GB的垃圾回收堆内存为例,V8做一次小的垃圾回收需要50毫秒以上,做一次非增量式的垃圾回收甚至要1秒以上。
这是垃圾回收中引起JavaScript线程暂停执行的时间,在这样的时间花销下,应用的性能和响应能力都会直线下降。这样的情况不仅仅后端服务无法接受前端浏览器也无法接受。
因此,在当时的考虑下直接限制堆内存是一个好的选择。
调整内存限制
当然,这个限制也不是不能打开,V8依然提供了选项让我们使用更多的内存。
Node在启动时可以传递--max-old-space-size或--max-new-space-size来调整内存限制的大小,示例如下:
node --max-old-space-size=1700 test.js // 单位为MB或者node --max-new-space-size=1024 test.js // 单位为KB
上述参数在V8初始化时生效,一旦生效就不能再动态改变。
如果遇到Node无法分配足够存给JavaScript对象的情况,可以用这个办法来放宽V8默认的内存限制,避免在执行过程中稍多用了一些内存就轻易崩溃。
参考资料
《深入浅出Node.js》-- 朴灵编著