nodejs浅谈

158 阅读4分钟

node打破了过去javascript只能在浏览器中运行的局面,前后端编程环境统一

image.png

js在前端浏览器环境就是操作dom,在服务端就是操作文件

特点

  • 异步I/O
  • 事件与回调函数
  • 单线程
  • 跨平台

image.png

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中,主要将内存分为新生代和老生代两代。新生代中的对象为存活时间较短的对象,
老生代中的对象为存活时间较长或常驻内存的对象。

image.png

--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) 时,会发生以下序列:

38c62070-a9c9-49aa-bd63-16c37c961328.png

  1. Node 的核心模块中的 JavaScript readFile 函数被调用。
  2. 该函数通过绑定调用到 C++函数。
  3. C++代码准备请求,然后将其传递给 libuv ,说“请读取这个文件。”
  4. libuv 获取请求并将其提交到其线程池执行。
  5. 关键的是,您的 JavaScript 代码会立即继续执行。 readFile 调用已返回 undefined 。
  6. 稍后,池中的一个线程完成文件读取。它通知 libuv 完成情况。
  7. libuv 然后将结果和相关回调放入事件循环的队列中处理。
  8. 在事件循环的下一个轮次中,它会在队列中看到完成的任务并执行您提供的原始 JavaScript 回调,传递数据或错误。