2013年2月20日 星期三

unix network programming: chapter 15 nonblocking IO

這一章特別有趣,因為之前node.js對於nonblocking IO有點消化不良,慢慢地體會到,nonblocking IO的思維之後,覺得這樣的設計對於performance真很有幫助,不過控制也是比較困難,這篇文章不會提到書中如何實作,想了解的網友可以直接翻閱書籍

最讓人直接聯想到的nonblocking IO思維是connect()這個function,如果說只有一個連線,個人認為block反而容易理解,nonblocking沒太大用途。但是想像一個應用,比方設計一個由地理位置分析周遭環境的application,你需要透過超過五十頁的網頁內容來整合,這時候connect()會block就變成了一個效能的瓶頸,因為每個網頁都要等前一個網頁的3-way handshake完成才能繼續工作,如果改用nonblocking,幾乎可以在短時間內就發出五十個http請求,這樣就快得多了

但是nonblocking其實也有些副作用
  • nonblocking非常耗用CPU效能
  • nonblocking的程式碼相對難以掌握,可以參考書中,由blocking/select IO(40 lines)膨脹成nonblocking IO的135 lines,可見一斑,
  • 書中沒有提到的流程控制相對困難,可參考node.js的flow control部分,就知道連流程控制也是一大挑戰
另外一個作者書中提到的效能比較也是一個很好的指標
  • block and wait version : 354(s)
  • select and blocking : 12.3 (s)
  • nonblocking IO: 6.9 (s)
  • fork(): 8.7 (s)
  • thread : 8.5 (s)
作者比較推薦簡易的版本fork()或者thread,因為nonblocking在程式碼控制方面比較困難

回過頭來說,其實上面選用除了第一個之外,各有各的不同考量,我給出的建議如下
nonblocking IO: performance
fork(): different task or paralle task
thread: similar task or share data

如果要同時發出大量的連線需求,使用nonblocking是比較好的選擇,如果資源充裕(memory很多/cpu也很強)使用fork()也比較好,因為thread遇到block IO整個process就被block住,其他thread也失去了活動機會,根本沒有幫助

如果說需要share data,基本上挑選thread會比較好,因為thread在share data表現上比IPC容易一點,雖然也有同步資料的問題,但是同步資料在fork()也是無法迴避的。相同的動作,如http server讀取檔案,使用thread就是不錯的選擇

fork()比thread的缺點就是要配置大量的記憶體空間,還有share data要透過IPC,好處是不會被block住。
此外process在kernel上分配CPU time的機會也比thread好,比方說目前server有一個process,programmer寫一個抓取遠端資料分析的程式,為了增進效能,將其一分為二,一個使用fork(),一個使用thread,那麼一個是三個process,一個是兩個process,如果均勻分配,使用fork()方式的將會佔據67%左右的CPU,另外一個使用thread只有33%。當然這是一種武斷的算法,要看使用的CPU/IO乃至於網路的情況而定

所以到底是該用nonblocking IO或者blocking IO?該用thread or fork()?其實都有不同的考量,由於richard stevens已經去世了,新版(3ed)的不知道有沒有討論到asynchronous IO??這或許再看看,在2ed richard stevens只是輕輕帶過這種IO的存在,事實上,網路上已經有開始有使用asynchrounous IO的文章了,應該是值得期待的

沒有留言:

張貼留言