Node.js日记:I/O

IO 概述

IO 在计算机中指 Input/Output,也就是输入和输出。

程序运行时需要获取数据在内存操作,而程序的执行由 CPU 这个超快的计算核心来负责,涉及到数据读写的通常是磁盘、网络等。

1)网络操作

网络操作中,比如你打开浏览器访问新浪首页,浏览器这个程序就需要通过网络 IO 获取新浪的网页。

浏览器首先会发送数据给新浪服务器,告诉它我想要首页的 HTML,这个动作是往外发数据,叫 Output;随后新浪服务器把网页发过来,这个动作是从外面接收数据,叫 Input。

2)文件操作(磁盘操作)

文件操作中,比如,从磁盘读取文件到内存,就只有 Input 操作,反过来,把数据写到磁盘文件里,就只是一个 Output 操作。

同步 IO 与异步 IO

由于 CPU 和内存的速度远远高于其他存储介质的速度,所以,在 IO 编程中,就存在速度严重不匹配的问题。

举个例子来说,比如要把 100M 的数据写入磁盘,CPU 输出 100M 的数据只需要 0.01 秒,可是磁盘要接收这 100M 数据可能需要 10 秒。

怎么办呢?

有两种办法:

- 第一种是 CPU 等着,也就是程序暂停执行后续代码(阻塞),等 100M 的数据在 10 秒后写入磁盘,再接着往下执行,这种模式称为同步 IO

- 另一种方法是 CPU 不等待,只是告诉磁盘,“您老慢慢写,不着急,我接着干别的事去了”,于是,后续代码可以立刻接着执行,这种模式称为异步 IO

同步和异步的区别就在于是否等待 IO 执行的结果。

好比你去麦当劳点餐,你说“来个汉堡”,服务员告诉你,对不起,汉堡要现做,需要等 5 分钟,于是你站在收银台前面等了 5 分钟,拿到汉堡再去逛商场,这是同步 IO。

你说“来个汉堡”,服务员告诉你,汉堡需要等 5 分钟,你可以先去逛商场,等做好了,我们再通知你,这样你可以立刻去干别的事情(逛商场),这是异步 IO。

同步 IO 要想提高系统系统吞吐量,可以使用多线程编程,因为一个线程阻塞时还有其他线程在工作,多线程可以让 CPU 资源不被阻塞中的线程浪费,多线程带来的好处仅仅是在多核 CPU 的情况下利用更多的核;

异步 IO,线程不会被 I/O 阻塞,永远在利用 CPU,I/O 以事件的方式通知。同步IO和异步IO比较:

同步式 I/O(阻塞式) 异步式 I/O(非阻塞式)
利用多线程提供吞吐量 单线程即可实现高吞吐量
通过事件片分割和线程调度利用多核CPU 通过功能划分利用多核CPU
需要由操作系统调度多线程使用多核 CPU 可以将单进程绑定到单核 CPU
难以充分利用 CPU 资源 可以充分利用 CPU 资源
数据局部性弱 数据局部性强
符合线性的编程思维 不符合传统编程思维

 

事件驱动

1)事件驱动模型

大部分的前端编程都是事件驱动模型,如页面元素会提供 onClick 事件,这个事件就代表鼠标按下事件。

事件驱动模型大致思路: 

- 有一个事件(消息)队列; 
- 鼠标按下时,往这个队列中增加一个点击事件(消息); 
- 有个循环,不断从队列取出事件,根据不同的事件,调用绑定在这些事件的函数。

事件驱动编程是一种编程范式,这里程序的执行流由外部事件来决定。

它的特点是包含一个事件循环,当外部事件发生时使用回调机制来触发相应的处理。

另外两种常见的编程范式是(单线程)同步以及多线程编程(编程复杂,因为这类程序不得不通过线程同步机制如锁、可重入函数、线程局部存储或者其他机制来处理线程安全问题,如果实现不当就会导致出现微妙且令人痛不欲生的 bug)。

2)Node.js 中的异步 IO 与事件驱动

Node.js 使用了单线程、非阻塞(异步IO)的事件编程模式。

好处是避免多线程的开销及多线程编程的难度,坏处是不符合人们一般的程序设计思维,容易让控制流变得晦涩难懂,给编码和调试都带来不小的困难。

代码举例:

const fs = require('fs');
fs.readFile('file.txt', 'utf-8', function(err, data) { // 基于回调函数的异步 IO 
    if (err) {
        console.error(err);
    } else {
        console.log(data);
    }
});
console.log('end');
const fs = require('fs');
var data = fs.readFileSync('file.txt', 'utf-8'); // 同步异步 IO 
console.log(data);
console.log('end');

注意:Node.js 中,并不是所有的 API 都提供了同步和异步版本。Node.js 不鼓励使用同步 I/O。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章