node是v8引擎实现的,所以是v8的内存管理。涉及到的主要方法有:
process.memoryUsage(),v8.getHeapSpaceStatistics(),v8.getHeapStatistics(),os.cpus(),os.totalmem();下面这个讨论,在开始讨论以前先说一下v8的内存管理机制:
由于历史原因和回收算法的限制,node在64位系统最大内存为1.4G左右,32位系统为0.7G左右,如果以1.5G内存为例,node做一次垃圾回收要50ms以上,做一次非增量式垃圾回收要1s以上,这是无法容忍的。v8里面分有两块新生代堆(new_heap)和老生代堆(old_heap),较为固定的放在老生代堆,容易移除的放在新生代堆,并且能有新生代到老生代转化,并且在新生代堆又分为form空间和to空间。用空间换取cpu执行时间(同时也导致了内存无法完全使用),这两个堆使用不同的算法进行管理。具体的算法回收流程这里不再介绍。
process.memoryUsage(),运行代码结果如下:
rss:Resident Set Size,是进程在主存中占用的空间,这是系统给node分配内存的一个子集。它包括堆,代码段,栈。对象,字符串存贮在堆里,变量存贮在栈里,js代码存贮在代码段空间。如果用buffer不断分配内存rss会持续增加, 超过node内存限制,只是buffer内存分配机制造成的。
heapTotal,heapUsed表示v8内存使用情况,
external 表示绑定到由V8管理的JavaScript对象的C++对象的内存使用。buffer内存在rss以外分配。
可以看出默认情况下系统为node分配的内存是很小的才20M。但是随着应用请求分配内存会不断增加,直到达到内存限制阈值而报错。
v8.getHeapSpaceStatistics()
这里我们只用关注new_space,和old_space就行了。说明了当下队内存的使用情况。
v8.getHeapStatistics()
这是堆统计数据,队内存默认是9M,可使用的内存1.4G,堆内存大小限制1.4G,已经使用的堆4M,很小的。
os.cpus()
数组里面对象的个数,代表服务器的内核数,nice是linux特有的window总是0,
IRQ:Interrupt ReQuest cpu中断请求。
SYS:CPU花了多少比例的时间在内核空间运行。分配内存、IO操作、创建子进程……都是内核操作。这也表明,当IO操作频繁时,System参数会很高。
user:cpu在用户代码上话费的时间。
Idel:CPU处于空闲状态时间比例。在计算机中,读写磁盘的操作远比CPU运行的速度要慢,CPU负载处理数据,而数据一般在磁盘上需要读到内存中才能处理。当CPU发起读写操作后,需要等着磁盘驱动器将数据读入内存,从而导致CPU 在等待的这一段时间内无事可做。CPU处于这种等待状态的时间由idel参数来衡量。
一般对node进行性能和内存监控都是以这几个函数为基础的。所以深入了解node的内存原理以及这几个函数是做好node性能监控的必要条件。