node打破了过去javascript只能在浏览器中运行的局面,前后端编程环境统一
js在前端浏览器环境就是操作dom,在服务端就是操作文件
特点
- 异步I/O
- 事件与回调函数
- 单线程
- 跨平台
node的虚拟机V8引擎
v8的内存限制
在一般的后端开发语言中,在基本的内存使用上没有什么限制,然而在Node中通过JavaScript
使用内存时就会发现只能使用部分内存(64位系统下约为1.4GB,32位系统下约为0.7GB)。
V8的对象分配
在V8中,所有的JavaScript对象都是通过堆来进行分配的
当我们在代码中声明变量并赋值时,所使用对象的内存就分配在堆中。如果已申请的堆空闲
内存不够分配新的对象,将继续申请堆内存,直到堆的大小超过V8的限制为止。
至于V8为何要限制堆的大小,表层原因为V8最初为浏览器而设计,不太可能遇到用大量内
存的场景。对于网页来说,V8的限制值已经绰绰有余。深层原因是V8的垃圾回收机制的限制。
按官方的说法,以1.5GB的垃圾回收堆内存为例,V8做一次小的垃圾回收需要50毫秒以上,做一次非增量式的垃圾回收甚至要1秒以上。这是垃圾回收中引起JavaScript线程暂停执行的时间,在这样的时间花销下,应用的性能和响应能力都会直线下降。这样的情况不仅仅后端服务无法接受,前端浏览器也无法接受。因此,在当时的考虑下直接限制堆内存是一个好的选择。
当然,这个限制也不是不能打开,V8依然提供了选项让我们使用更多的内存。Node在启动
时可以传递--max-old-space-size或--max-new-space-size来调整内存限制的大小,示例如下:
node-- max- old- space- size=1700 test. is//单位为 MB
//或者
node --max-new-space-size=1024 test. js //单为KB
V8的垃圾回收机制
V8的内存分代
在V8中,主要将内存分为新生代和老生代两代。新生代中的对象为存活时间较短的对象,
老生代中的对象为存活时间较长或常驻内存的对象。
--max-old-space-size命令行参数可以用于设置老生代内存空间的最大值,--max-new-space-size
命令行参数则用于设置新生代内存空间的大小的
Node.js 不是一个语言、框架或库;它是一个运行时环境。它是一个在浏览器外执行您的 JavaScript 代码的程序。它由三个主要部分组成:
-
V8 JavaScript 引擎。来自 Google Chrome 的相同高性能引擎。它将您的 JS 编译成原生机器代码。
-
C++ 绑定与 Node.js 核心 API。连接您的 JavaScript(
require('fs'))到底层 C++和libuv功能的“胶水”,允许您访问文件系统、网络等 -
libuv库。一个 C 库,提供了异步、非阻塞的 I/O 模型。这里是事件循环和线程池魔法发生的地方。这是 Node 的秘密武器。
当你编写 const fs = require('fs'); 时,你并不是得到一个纯 JavaScript 对象。你得到的是一个具有“绑定”到底层 C++代码的 JavaScript 模块。当你调用 fs.readFile('/path/to/file', callback) 时,会发生以下序列:
- Node 的核心模块中的 JavaScript
readFile函数被调用。 - 该函数通过绑定调用到 C++函数。
- C++代码准备请求,然后将其传递给
libuv,说“请读取这个文件。” libuv获取请求并将其提交到其线程池执行。- 关键的是,您的 JavaScript 代码会立即继续执行。
readFile调用已返回undefined。 - 稍后,池中的一个线程完成文件读取。它通知
libuv完成情况。 libuv然后将结果和相关回调放入事件循环的队列中处理。- 在事件循环的下一个轮次中,它会在队列中看到完成的任务并执行您提供的原始 JavaScript 回调,传递数据或错误。