閱讀858 返回首頁    go 微軟 go windows


關於NIO

操作係統的IO控製

在整個IO控製方式的發展過程中,始終貫穿著這樣一條宗旨:即盡量減少主機對IO控製的幹預,把主機從繁雜的IO控製事務中解脫出來,以便更多地去完成數據處理任務。為了緩和高速CPU和IO設備低速間的矛盾,現代操作係統使用通道技術,SPOOLING技術,以及緩衝技術可以做到IO操作由特殊的IO處理器(通道)負責執行,隻是在IO開始和結束時,調用CPU中斷處理,從而使CPU資源不被IO占用,充分發揮了CPU使用效率。

所以下文要討論的BIO和NIO,從操作係統對設備管理的角度來說,其CPU使用率都是相同的,因為相同操作係統對設備管理和IO控製是相同的。 隻是NIO使用的線程少,所以占用的內存少,減輕了係統對上下文切換的開銷。


參考:
https://www.cnblogs.com/loveyakamoz/archive/2012/11/14/2770810.html
https://daimojingdeyu.iteye.com/blog/828696

什麼是NIO

In computer science, asynchronous I/O, or non-blocking I/O is a form of input/output processing that permits other processing to continue before thetransmission has finished.

Input and output (I/O) operations on a computer can be extremely slow compared to the processing of data. An I/O device can incorporate mechanical devices that must physically move, such as a hard drive seeking a track to read or write; this is often orders of magnitude slower than the switching of electric current. For example, during a disk operation that takes ten milliseconds to perform, a processor that is clocked at one gigahertz could have performed ten million instruction-processing cycles.

參考:
https://en.wikipedia.org/wiki/Non-blocking_I/O

為什麼要NIO


為每個客戶端分配一個線程進行IO操作的弊端


這種IO模型已經在了幾十年了,這種策略下,read和write調用都是堵塞的。它最大的問題就是每個線程都要占用一個完整的棧幀,假設棧幀的空間為2M,那麼1G的內存最多服務512個線程,顯然和10K有不小差距。當然,由於硬件資源越來越便宜,線程的內存開銷可能不會成為瓶頸。但多線程帶來的進程切換的開銷卻有可能長期存在。


每個客戶端一個線程


用一個線程服務所有客戶端,後端采用NIO,此技術類似於通信的多路複用(Multiplexing) https://en.wikipedia.org/wiki/Multiplexing


所以NIO的主要優勢是,其運用內核的IO線程,從而能夠以較小的內存占用和較高的CPU使用效率支持大並發訪問。此處需要注意的是並不是所有的操作係統就原生支持這種IO策略,例如*nix (Linux, Unix) 就不支持,所以其異步IO(AIO:Asynchronous IO) 其實是通過采用線程池與阻塞IO模擬異步IO,相反,在windows平台下的IOCP,它在某種程度上提供了理想的異步IO:調用異步方法,等待IO完成之後的通知,執行回調,用戶無須考慮輪詢。其背後原理依然是線程池,不同之處在於這些線程池由係統內核接受管理,所以占用內存小,上下文切換的代價也低。


異步IO帶來的性能提升

就像前麵關於NIO定義描述的,IO操作占據了程序運行中絕大部分時間,以數據訪問所需要的開銷為例(p48 NodeJS),訪問CPU一級緩存需要3個CPU時鍾周期,訪問內存需要250個,訪問硬盤需要41000000個,而訪問網絡則需要240000000個時鍾周期。

所以異步IO能夠帶來明顯的性能提升,例如一個業務需要執行如下操作

//消費時間為M
getData ('from db')

//消費時間為N
doOperate('from remote API')

如果是同步阻塞IO,其所需時間為M+N, 如果是異步IO,其所需時間為Max(M, N),可見其性能提升是很明顯的。

異步IO帶來的吞吐量提升

大家都知道建立TCP connection是比較耗時的,如果采用阻塞式的方式,勢必會影響服務器的TPS,在我的下一遍關於BIO和NIO的性能分析中,有詳細的測試報告,測試結果大概是BIO Accept一個TCP connection的時間大概是NIO的十倍。

我的觀點

雖然最近Node和NIO很火,也不就意味著像Apache那種傳統的Thread Per Request就到了世界末日了,至少eBay這麼大流量的網站,並沒有發現Apache Server是性能的瓶頸,瓶頸往往是在數據庫上。特別是在Linux係統中,用線程池模擬異步IO,而係統內核又沒有原生支持的情況下,我並沒有發現其相比較於Apache有什麼本質的提升, OK,Node的支持者,也許馬上會反駁道,你剛剛不是說數據庫是性能瓶頸嗎,異步IO可以用異步的方式去訪問數據庫啊(上麵的例子),可以將M+N的時間降低為Max(M,N),這不是性能提升麼

事實果真是這樣嗎?不盡然,因為前後兩次操作往往並不是獨立的,而是有依賴關係的,也就是說doOperate必須等待getData的結果才能去做,在這種情況下,業務完成時間還是需要M+N。 不過對於網絡服務器吞吐量提升和對於大並發的支持,這倒是不爭的事實

NIO的缺點是編程過於複雜,如果處理不當,不但不能提高效率,反而會浪費係統資源,綜合其優缺點,我個人覺得除非大並發真的變成係統瓶頸,否則最好謹慎使用NIO這把雙刃劍


參考: 
IO vs NIO: https://tutorials.jenkov.com/java-nio/nio-vs-io.html
同步和異步IO,阻塞和非阻塞IO:https://www.360doc.com/content/12/0604/15/9579107_215831239.shtml
c10K問題: https://www.360doc.com/content/13/0522/18/1542811_287328391.shtml

最後更新:2017-04-03 08:26:17

  上一篇:go 明天的數字營銷分析工具二
  下一篇:go C# 係統應用之ListView控件 (三).添加ContextMenuStrip右鍵菜單打開刪除文件