- 論壇徽章:
- 0
|
現(xiàn)在流行的 web 服務(wù)器里面都提供 sendfile 選項用來提高服務(wù)器性能,那到底 sendfile 是什么,怎么影響性能的呢?sendfile 實際上是 Linux 2.0+ 以后的推出的一個系統(tǒng)調(diào)用,web 服務(wù)器可以通過調(diào)整自身的配置來決定是否利用 sendfile 這個系統(tǒng)調(diào)用。先來看一下不用 sendfile 的傳統(tǒng)網(wǎng)絡(luò)傳輸過程:
read(file, tmp_buf, len);
write(socket, tmp_buf, len);
硬盤 >> kernel buffer >> user buffer >> kernel socket buffer >> 協(xié)議棧
一般來說一個網(wǎng)絡(luò)應(yīng)用是通過讀硬盤數(shù)據(jù),然后寫數(shù)據(jù)到 socket 來完成網(wǎng)絡(luò)傳輸?shù)。上?行用代碼解釋了這一點,不過上面2行簡單的代碼掩蓋了底層的很多操作。來看看底層是怎么執(zhí)行上面2行代碼的:
1、系統(tǒng)調(diào)用 read() 產(chǎn)生一個上下文切換:從 user mode 切換到 kernel mode,然后 DMA 執(zhí)行拷貝,把文件數(shù)據(jù)從硬盤讀到一個 kernel buffer 里。
2、數(shù)據(jù)從 kernel buffer 拷貝到 user buffer,然后系統(tǒng)調(diào)用 read() 返回,這時又產(chǎn)生一個上下文切換:從kernel mode 切換到 user mode。
3、系統(tǒng)調(diào)用 write() 產(chǎn)生一個上下文切換:從 user mode 切換到 kernel mode,然后把步驟2讀到 user buffer 的數(shù)據(jù)拷貝到 kernel buffer(數(shù)據(jù)第2次拷貝到 kernel buffer),不過這次是個不同的 kernel buffer,這個 buffer 和 socket 相關(guān)聯(lián)。
4、系統(tǒng)調(diào)用 write() 返回,產(chǎn)生一個上下文切換:從 kernel mode 切換到 user mode(第4次切換了),然后 DMA 從 kernel buffer 拷貝數(shù)據(jù)到協(xié)議棧(第4次拷貝了)。
上面4個步驟有4次上下文切換,有4次拷貝,我們發(fā)現(xiàn)如果能減少切換次數(shù)和拷貝次數(shù)將會有效提升性能。在kernel 2.0+ 版本中,系統(tǒng)調(diào)用 sendfile() 就是用來簡化上面步驟提升性能的。sendfile() 不但能減少切換次數(shù)而且還能減少拷貝次數(shù)。
再來看一下用 sendfile() 來進行網(wǎng)絡(luò)傳輸?shù)倪^程:
sendfile(socket, file, len);
硬盤 >> kernel buffer (快速拷貝到kernel socket buffer) >> 協(xié)議棧
1、系統(tǒng)調(diào)用 sendfile() 通過 DMA 把硬盤數(shù)據(jù)拷貝到 kernel buffer,然后數(shù)據(jù)被 kernel 直接拷貝到另外一個與 socket 相關(guān)的 kernel buffer。這里沒有 user mode 和 kernel mode 之間的切換,在 kernel 中直接完成了從一個 buffer 到另一個 buffer 的拷貝。
2、DMA 把數(shù)據(jù)從 kernel buffer 直接拷貝給協(xié)議棧,沒有切換,也不需要數(shù)據(jù)從 user mode 拷貝到 kernel mode,因為數(shù)據(jù)就在 kernel 里。
步驟減少了,切換減少了,拷貝減少了,自然性能就提升了。這就是為什么說在 Nginx 配置文件里打開 sendfile on 選項能提高 web serve r性能的原因。
本文來自ChinaUnix博客,如果查看原文請點:http://blog.chinaunix.net/u2/61207/showart_2053382.html |
|