Linux大檔案重定向和管道的效率對比總結
導讀 | 大家先看一下二個 ,假如huge_dump.sql檔案很大,然後猜測一下哪種匯入方式效率會更高一些? |
# 命令1,管道匯入 shell> cat huge_dump.sql | mysql -uroot;
# 命令2,重定向匯入 shell> mysql -uroot < huge_dump.sql;
大家先看一下上面二個命令,假如huge_dump.sql檔案很大,然後猜測一下哪種匯入方式效率會更高一些?
這個問題挺有意思的,我的第一反應是:沒比較過,應該是一樣的,一個是cat負責開啟檔案,一個是bash
這種場景在MySQL運維操作裡面應該比較多,所以就花了點時間做了個比較和原理上的分析:
我們先構造場景:
首先準備一個程式b.out來模擬mysql對資料的消耗:
int main(int argc, char *argv[]) while(fread(buf, sizeof(buf), 1, stdin) > 0); return 0; } $ gcc -o b.out b.c $ ls|./b.out
再來寫個systemtap 用來方便觀察程式的行為。
$ cat test.stp function should_log(){ return (execname() == "cat" || execname() == "b.out" || execname() == "bash") ; } probe syscall.open, syscall.close, syscall.read, syscall.write, syscall.pipe, syscall.fork, syscall.execve, syscall.dup, syscall.wait4 { if (!should_log()) next; printf("%s -> %s\n", thread_indent(0), probefunc()); } probe kernel.function("pipe_read"), kernel.function("pipe_readv"), kernel.function("pipe_write"), kernel.function("pipe_writev") { if (!should_log()) next; printf("%s -> %s: file ino %d\n", thread_indent(0), probefunc(), __file_ino($filp)); } probe begin { println(":~") }
這個 重點觀察幾個系統呼叫的順序和pipe的讀寫情況,然後再準備個419M的大檔案huge_dump.sql,在我們幾十G記憶體的機器很容易在記憶體裡放下:
$ sudo dd if=/dev/urandom of=huge_dump.sql bs=4096 count=102400 102400+0 records in 102400+0 records out 419430400 bytes (419 MB) copied, 63.9886 seconds, 6.6 MB/s
因為這個檔案是用bufferio寫的,所以它的內容都cache在pagecahce記憶體裡面,不會涉及到磁碟。
好了,場景齊全了,我們接著來比較下二種情況下的速度,第一種管道:
# 第一種管道方式 $ time (cat huge_dump.sql|./b.out) real 0m0.596s user 0m0.001s sys 0m0.919s
從執行時間數看出來速度有3倍左右的差別了,第二種明顯快很多。
是不是有點奇怪?好吧我們來從原來上面分析下,還是繼續用資料說話:
這次準備個很小的資料檔案,方便觀察然後在一個視窗執行stap
$ echo hello > huge_dump.sql $ sudo stap test.stp :~ 0 bash(26570): -> sys_read 0 bash(26570): -> sys_read 0 bash(26570): -> sys_write 0 bash(26570): -> sys_read 0 bash(26570): -> sys_write 0 bash(26570): -> sys_close 0 bash(26570): -> sys_pipe 0 bash(26570): -> sys_pipe 0 bash(26570): -> do_fork 0 bash(26570): -> sys_close 0 bash(26570): -> sys_close 0 bash(26570): -> do_fork 0 bash(13775): -> sys_close 0 bash(13775): -> sys_read 0 bash(13775): -> pipe_read: file ino 20906911 0 bash(13775): -> pipe_readv: file ino 20906911 0 bash(13776): -> sys_close 0 bash(13776): -> sys_close 0 bash(13776): -> sys_close 0 bash(13776): -> do_execve 0 bash(26570): -> sys_close 0 bash(26570): -> sys_close 0 bash(26570): -> sys_close 0 bash(13775): -> sys_close 0 bash(26570): -> sys_wait4 0 bash(13775): -> sys_close 0 bash(13775): -> sys_close 0 b.out(13776): -> sys_close 0 b.out(13776): -> sys_close 0 bash(13775): -> do_execve 0 b.out(13776): -> sys_open 0 b.out(13776): -> sys_close 0 b.out(13776): -> sys_open 0 b.out(13776): -> sys_read 0 b.out(13776): -> sys_close 0 cat(13775): -> sys_close 0 cat(13775): -> sys_close 0 b.out(13776): -> sys_read 0 b.out(13776): -> pipe_read: file ino 20906910 0 b.out(13776): -> pipe_readv: file ino 20906910 0 cat(13775): -> sys_open 0 cat(13775): -> sys_close 0 cat(13775): -> sys_open 0 cat(13775): -> sys_read 0 cat(13775): -> sys_close 0 cat(13775): -> sys_open 0 cat(13775): -> sys_close 0 cat(13775): -> sys_open 0 cat(13775): -> sys_read 0 cat(13775): -> sys_write 0 cat(13775): -> pipe_write: file ino 20906910 0 cat(13775): -> pipe_writev: file ino 20906910 0 cat(13775): -> sys_read 0 b.out(13776): -> sys_read 0 b.out(13776): -> pipe_read: file ino 20906910 0 b.out(13776): -> pipe_readv: file ino 20906910 0 cat(13775): -> sys_close 0 cat(13775): -> sys_close 0 bash(26570): -> sys_wait4 0 bash(26570): -> sys_close 0 bash(26570): -> sys_wait4 0 bash(26570): -> sys_write
stap在收集資料了,我們在另外一個視窗執行管道的情況:
$ cat huge_dump.sql|./b.out
我們從systemtap的日誌可以看出:
- bash fork了2個程式。
- 然後execve分別執行cat 和 b.out程式, 這二個程式用pipe通訊。
- 資料從由cat從 huge_dump.sql讀出,寫到pipe,然後b.out從pipe讀出處理。
那麼再看下命令2重定向的情況:
$ ./b.out < huge_dump.sql stap輸出: 0 bash(26570): -> sys_read 0 bash(26570): -> sys_read 0 bash(26570): -> sys_write 0 bash(26570): -> sys_read 0 bash(26570): -> sys_write 0 bash(26570): -> sys_close 0 bash(26570): -> sys_pipe 0 bash(26570): -> do_fork 0 bash(28926): -> sys_close 0 bash(28926): -> sys_read 0 bash(28926): -> pipe_read: file ino 20920902 0 bash(28926): -> pipe_readv: file ino 20920902 0 bash(26570): -> sys_close 0 bash(26570): -> sys_close 0 bash(26570): -> sys_wait4 0 bash(28926): -> sys_close 0 bash(28926): -> sys_open 0 bash(28926): -> sys_close 0 bash(28926): -> do_execve 0 b.out(28926): -> sys_close 0 b.out(28926): -> sys_close 0 b.out(28926): -> sys_open 0 b.out(28926): -> sys_close 0 b.out(28926): -> sys_open 0 b.out(28926): -> sys_read 0 b.out(28926): -> sys_close 0 b.out(28926): -> sys_read 0 b.out(28926): -> sys_read 0 bash(26570): -> sys_wait4 0 bash(26570): -> sys_write 0 bash(26570): -> sys_read
現在就非常清楚為什麼二種場景速度有3倍的差別:
結論: 下大檔案重定向效率更高。
原文來自:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69955379/viewspace-2682795/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Linux的管道機制和重定向Linux
- Linux中重定向和管道介紹Linux
- 在Linux中,管道(pipe)和重定向(redirection)的是什麼?Linux
- Java 大檔案IO操作效率對比【我說說 你瞅瞅】Java
- linux的I/O重定向和管道的檔案描述符運用,及shell如何實現多執行緒?Linux執行緒
- ReferenceField、EmbeddedDocumentField和LazyReferenceField的使用和總結對比
- .ts檔案和d.ts檔案對比
- Linux-task_struct和檔案系統及管道的關係LinuxStruct
- 【資料結構】棧和佇列的總結對比資料結構佇列
- 比對檔案sam檔案的解讀
- linux3-管道符、重定向、環境變數Linux變數
- 強大的檔案對比工具Beyond Compare 4 for MacMac
- 輸出重定向 管道
- 介紹 Linux 中的管道和命名管道Linux
- Python檔案操作方法大總結Python
- Windows&Linux檔案傳輸方式總結WindowsLinux
- Linux中檔案/檔案系統的壓縮、打包和備份總結(基於rhel7)Linux
- TCP/UDP對比總結TCPUDP
- 使用檔案重定向
- 分散式檔案系統(HDFS)與 linux系統檔案系統 對比分散式Linux
- 015 Linux 標準輸入輸出、重定向、管道和後臺啟動程式命令Linux
- Linux歸檔及壓縮、重定向與管道操作、find精確查詢、vim高階使用Linux
- Linux系統中有哪些比較重要的檔案系統結構?Linux
- 檔案內容對比工具
- 位移符效率對比
- Zsh 開發指南(第十三篇 管道和重定向)
- mysql事務對效率的影響分析總結JILEMySql
- Beyond Compare for Mac(檔案比較對比工具)Mac
- Linux檔案的路徑定位-相對路徑和絕對路徑Linux
- python中的__init__.py檔案和導包總結Python
- HTTP總結(簡介、狀態碼和各版本對比)HTTP
- 【ASM】ASM資料檔案和OS檔案(FILESYSTEM)轉移方法總結ASM
- Git比對檔案之間的差異Git
- linux中的輸入與輸出管理(重定向輸入,輸出,管道符)Linux
- MyBatis配置檔案總結MyBatis
- Linux---檔案、軟連結於硬連結檔案Linux
- Kaleidoscope for Mac Mac檔案對比工具Mac
- Java位元組流檔案複製及效率比較Java