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。

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