sendfile()對nginx性能的提升

Linux kernel 2.2之前,(如圖)讀寫數據基本都是使用read系統調用和write系調用,以nginx來說如果一個請求建立,從磁盤的文件到網絡連接之間會通過硬件(DMA)---內核層---用戶層多次讀寫系統來完成文件數據的複製傳輸:從內核層用read系統調用讀到用戶層,再從用戶層用write系統調用寫到內核層,每一次用戶層到內核層的進行一次上下文轉換,這種代價是非常昂貴的。甚至在沒有數據變化時這種複製尤其顯得多餘。如果nginx接受大量併發請求,這種系統調用就會非常頻繁,服務器的性能就會下降。

 

wKiom1OC_0Oih4A7AADfiB_7GRE907.jpg

 

在Linux kernel2.2版本之後出現了一種叫做“零拷貝(zero-copy)”系統調用機制,目前很多應用服務器如apache、samba、nginx都支持sendfile。注意:sendfile系統調用是一種文件傳輸的系統調用和kernel系統調用關係不大。

 

wKiom1ODB92wC3m3AADAG83M0Mg738.jpg

 

如圖所示,nginx在支持了sendfile系統調用後,避免了內核層與用戶層的上線文切換(content swith)工作,大大減少了系統性能的開銷。

可以使用man 8 sendfile 進一步瞭解sendfile系統調用。

wKioL1ODENTx2Hf5AADvMSIdktA859.jpg

以下是對參數解釋

out_fd

a file descriptor, open for writing, for the data to be written

in_fd

a file descriptor, open for reading, for the data to be read

offset

the offset in the input file to start transfer (e.g. a value of 0 indicates the beginning of the file). This is passed into the function and updated when the function returns.

count

the number of bytes to be transferred

正常情況下函數會返回被寫入的字節數,如果出錯就返回-1

我們都知道在linux系統裏文件描述符fd,可以是一個真實的文件或者是一個設備,例如一個網絡socket,(當然linux世界裏一切皆文件,這裏只是具體區別一下。)senfile需要輸入的文件描述符是一個支持mmap的真實文件或者設備,那麼socket就不能作爲輸入的fd,而輸出的fd是可以的。

具體在nginx的使用中可以通過在配置文件nginx.conf中增加參數使用sendfile

http {

        sendfile on;

        tcp_nopush on;

        tcp_nodelay on;        

        ...........................

}

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